/** * 得到一个文件基本信息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; }
/** * 初始化fileSummaryContext * @param string $project_path */ private function initFileSummaryContext($project_path, $allFiles) { global $project_path; $fileName = str_replace('/', '_', $project_path); $fileName = str_replace(':', '_', $fileName); $serialPath = CURR_PATH . "/data/fileSummaryConetxtSerialData/" . $fileName; if (!is_file($serialPath)) { //创建文件 $fileHandler = fopen($serialPath, 'w'); fclose($fileHandler); } //判断本地序列化文件中是否存在UserSanitizeFuncConetxt if (($serial_str = file_get_contents($serialPath)) != '') { $fileSummaryMap = unserialize($serial_str); $fileSummaryContext = FileSummaryContext::getInstance(); $fileSummaryContext->setFileSummaryMap($fileSummaryMap); return; } //没有序列化,则获取fileSummary $fileSummaryContext = FileSummaryContext::getInstance(); foreach ($allFiles as $fileAbsPath) { $ret = FileSummaryGenerator::getFileSummary($fileAbsPath); if ($ret) { $fileSummaryContext->addSummaryToMap($ret); } } //对FileSummaryContext进行序列化,加快下次读取速度 $this->serializeContext($serialPath, $fileSummaryContext->getFileSummaryMap()); }
private static function sanitiSameVarMultiFileHandler($varName, $block, $dataFlows, $fileSummary) { $includeFileSummaryMap = FileSummaryGenerator::getIncludeFilesDataFlows($fileSummary); if (!$includeFileSummaryMap) { return array(false); } $includeFileSummaryMap = array_reverse($includeFileSummaryMap); foreach ($includeFileSummaryMap as $includeFileSummary) { if (!$includeFileSummary instanceof FileSummary) { continue; } $fileDataFlows = $includeFileSummary->getFlowsMap(); $fileDataFlows = array_reverse($fileDataFlows); foreach ($fileDataFlows as $flow) { if ($flow->getName() == $varName) { if ($flow->getlocation()) { $ret = $flow->getlocation()->getSanitization(); if ($ret) { return array(true, 'funcs' => $ret); } else { return array(false); } } } } } }
/** * 多文件间分析 * @param BasicBlock $block 当前基本块 * @param string $argName 漏洞变量 * @param Node $node 调用sink的node * @param array $fileSummaryMap 要分析的require文件的summary的list */ public function multiFileHandler($block, $argName, $node, $fileSummary, $flowNum = 0) { //首先根据fileSummary获取到fileSummaryMap $fileSummaryMap = FileSummaryGenerator::getIncludeFilesDataFlows($fileSummary); if (!$fileSummaryMap) { return; } $node_path = $fileSummary->getPath(); foreach ($fileSummaryMap as $fsummary) { if ($fsummary instanceof FileSummary) { $flows = $fsummary->getFlowsMap(); $tempNum = $flowNum; while ($tempNum) { $tempNum--; array_shift($flows); } foreach ($flows as $flow) { $flowNum++; if ($flow->getName() == $argName) { //处理净化信息,如果被编码或者净化则返回safe //被isSanitization函数取代 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) { $varName = $this->getVarName($var); //如果var右边有source项 if (in_array($varName, $this->sourcesArr)) { //报告漏洞 $var_path = $fsummary->getPath(); $this->report($node_path, $var_path, $node, $flow->getLocation(), $type); } } } } } } }