/** * 根据方法名查询sink所属的漏洞类别 * @param string $funcName * @return string */ public static function getTypeByFuncName($funcName) { //系统内置sink global $F_SINK_ALL, $F_SINK_ARRAY; //用户自定义sink $userDefinedSink = UserDefinedSinkContext::getInstance(); $U_SINK_ALL = $userDefinedSink->getAllSinks(); //系统sink if (key_exists($funcName, $F_SINK_ALL)) { foreach ($F_SINK_ARRAY as $value) { if (key_exists($funcName, $value)) { return $value['__NAME__']; } } } //用户sink if (key_exists($funcName, $U_SINK_ALL)) { foreach ($userDefinedSink->getAllSinkArray() as $value) { if (key_exists($funcName, $value)) { return $value['__NAME__']; } } } return NULL; }
/** * 根据净化栈和漏洞类型判断是否受到净化 * @param string $type 漏洞类型 * @param array $sanitiArr 净化栈 * @return bool true 表示受到净化 false反之 */ public static function checkSanitiByArr($type, $sanitiArr) { //获取用户自定义sink上下文 $userDefSinkContext = UserDefinedSinkContext::getInstance(); //判断sanitiArr中是否存在list中 $userDefSinkSaniti = $userDefSinkContext->getSinksSanitiByType($type); $confDefSinkSaniti = self::getSecureListByType($type); $commonDefSinkSaniti = self::getCommonSecureList(); $combine_list = array_merge($userDefSinkSaniti, $confDefSinkSaniti, $commonDefSinkSaniti); foreach ($sanitiArr as $value) { if (in_array($value->funcName, $combine_list)) { return true; } } return false; }
/** * 根据sink方法的名称获取危险参数的位置 * 比如提交mysql_query的调用node,返回危险参数位置array(0) * 如果找不到,默认返回array() * @param Node $node */ public static function getVulArgs($node) { global $F_SINK_ALL, $F_SINK_ARRAY; $funcName = NodeUtils::getNodeFunctionName($node); $nameNum = count($F_SINK_ARRAY); //从上下文中获取用户定义sink $userDefinedSink = UserDefinedSinkContext::getInstance(); $U_SINK_ALL = $userDefinedSink->getAllSinks(); //如果是系统的sink if (key_exists($funcName, $F_SINK_ALL)) { for ($i = 0; $i < $nameNum; $i++) { if (key_exists($funcName, $F_SINK_ARRAY[$i])) { return $F_SINK_ARRAY[$i][$funcName][0]; } } return array(); } //如果是用户的sink if (key_exists($funcName, $U_SINK_ALL)) { foreach ($userDefinedSink->getAllSinkArray() as $value) { if (key_exists($funcName, $value)) { return $U_SINK_ALL[$funcName][0]; } } return array(); } }
/** * 处理函数调用 * @param node $node 调用方法的节点 * @param BasicBlock $block 当前基本块 * @param fileSummary $fileSummary 当前文件摘要 */ public function functionHandler($node, $block, $fileSummary) { //根据用户指定的扫描类型,查找相类型的sink函数 global $scan_type; //获取调用的函数名判断是否是sink调用 $funcName = NodeUtils::getNodeFunctionName($node); //判断是否为sink函数,返回格式为array(true,funcname) or array(false) $ret = NodeUtils::isSinkFunction($funcName, $scan_type); if ($ret[0] != null && $ret[0] === true) { //如果发现了sink调用,启动污点分析 $analyser = new TaintAnalyser(); //获取危险参数的位置 $argPosition = NodeUtils::getVulArgs($node); if (count($argPosition) == 0) { return; } //获取到危险参数位置的变量 $argArr = NodeUtils::getFuncParamsByPos($node, $argPosition); //遍历危险参数名,调用污点分析函数 if (count($argArr) > 0) { foreach ($argArr as $item) { if (is_array($item)) { foreach ($item as $v) { $analyser->analysis($block, $node, $v, $fileSummary); } } else { $analyser->analysis($block, $node, $item, $fileSummary); } } } } else { //如果不是sink调用,启动过程间分析 $context = Context::getInstance(); $funcBody = $context->getClassMethodBody($funcName, $this->fileSummary->getPath(), $this->fileSummary->getIncludeMap()); //check if (!$funcBody || !is_object($funcBody)) { return; } if ($funcBody->getType() == "Stmt_ClassMethod") { $funcBody->stmts = $funcBody->stmts[0]; } //构建相应方法体的block和summary $nextblock = $this->CFGBuilder($funcBody->stmts, NULL, NULL, NULL); //ret危险参数的位置比如:array(0) $ret = $this->sinkFunctionHandler($funcBody, $nextblock, $block); if (!$ret) { return; } //找到了array('del',array(0)) ; $userDefinedSink = UserDefinedSinkContext::getInstance(); //$type应该从visitor中获取,使用$ret返回 $type = $ret['type']; unset($ret['type']); //加入用户sink上下文 $item = array($funcName, $ret); $userDefinedSink->addByTagName($item, $type); //开始污点分析 $argPosition = NodeUtils::getVulArgs($node); $argArr = NodeUtils::getFuncParamsByPos($node, $argPosition); if (count($argArr) > 0) { $analyser = new TaintAnalyser(); foreach ($argArr as $item) { if (is_array($item)) { foreach ($item as $v) { $analyser->analysis($block, $node, $v, $this->fileSummary); } } else { $analyser->analysis($block, $node, $item, $this->fileSummary); } } } } }