/** * 得到一个文件基本信息FileSummary,包括路径,基本块,包含的文件等 * @param string $absPath */ public static function getFileSummary($absPath) { if (!$absPath) { return; } $visitor = new MyVisitor(); $parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative()); $traverser = new PhpParser\NodeTraverser(); $code = file_get_contents($absPath); try { $stmts = $parser->parse($code); } catch (Exception $e) { return; } $traverser->addVisitor($visitor); $traverser->traverse($stmts); $nodes = $visitor->getNodes(); $fileSummary = new FileSummary(); $fileSummary->setPath($absPath); $currBlock = new BasicBlock(); foreach ($nodes as $node) { if (!is_object($node)) { continue; } //不分析函数定义 if ($node->getType() == "Stmt_Function") { continue; } $currBlock->addNode($node); } $fileSummaryGenerator = new FileSummaryGenerator(); $fileSummaryGenerator->simulate($currBlock, $fileSummary); return $fileSummary; }
/** * 污点分析中,对当前基本块的探测 * @param BasicBlock $block 当前基本块 * @param Node $node 当前调用sink的node * @param string $argName 危险参数的名称 * @param FileSummary $fileSummary 当前文件的文件摘要 * */ public function currBlockTaintHandler($block, $node, $argName, $fileSummary, $flowNum = 0) { $tempNum = $flowNum; //获取数据流信息 $flows = $block->getBlockSummary()->getDataFlowMap(); $flows = array_reverse($flows); //逆序处理flows //将处理过的flow移除 while ($tempNum) { $tempNum--; array_shift($flows); } foreach ($flows as $flow) { $flowNum++; if ($flow->getName() == $argName) { //处理净化信息,如果被编码或者净化则返回safe //先对左边的变量进行查询 if (is_object($flow->getLocation())) { $target = $flow->getLocation(); $type = TypeUtils::getTypeByFuncName(NodeUtils::getNodeFunctionName($node)); $encodingArr = $target->getEncoding(); $saniArr = $target->getSanitization(); $res = $this->isSanitization($type, $target, $saniArr, $encodingArr); if ($res == true) { return "safe"; } } //获取flow中的右边赋值变量 //得到flow->getValue()的变量node //$sql = $a . $b ; => array($a,$b) $vars = $this->getVarsByFlow($flow); foreach ($vars as $var) { if ($var instanceof ValueSymbol || !is_object($var)) { continue; } $varName = $this->getVarName($var); //如果var右边有source项 if (in_array($varName, $this->sourcesArr)) { // $ret = $this->multiFileHandler($block, $varName, $node, $fileSummary) ; // if($ret == 'safe'){ // continue ; // } //报告漏洞 $path = $fileSummary->getPath(); $this->report($path, $path, $node, $flow->getLocation(), $type); continue; } else { //首先进行文件夹的分析 $this->multiFileHandler($block, $varName, $node, $fileSummary); //文件间分析失败,递归 $this->currBlockTaintHandler($block, $node, $varName, $fileSummary, $flowNum); } } } } }