/** * @param mixed $uri The URI of the node. * @throws \Exception If parameter $value is not a valid URI. */ public function __construct($uri) { if ($uri == null || !NodeUtils::simpleCheckURI($uri)) { throw new \Exception('Parameter $uri is not a valid URI: ' . $uri); } $this->uri = $uri; }
/** * 处理赋值性的一些内置函数 * 比如: * $id = urlencode($_GET['id']) ; * @param unknown $part * @param unknown $type * @param unknown $dataFlow */ public static function assignFuncHandler($part, $type, $dataFlow, $funcName) { $single_func = self::getSingleFuncs(); $encoding_convert = array('iconv'); if ($type == "right" && array_key_exists($funcName, $single_func)) { //首先搜索不安全字符的转换函数 if (in_array($funcName, $encoding_convert)) { $oneFunction = new OneFunction($funcName); $dataFlow->getLocation()->addSanitization($oneFunction); } $position = $single_func[$funcName]; $value = $part->args[$position]->value; //解决trim(urlencode($id))的方法嵌套问题 if ($value->getType() == 'Expr_FuncCall') { $new_name = NodeUtils::getNodeFunctionName($value); self::assignFuncHandler($value, $type, $dataFlow, $new_name); } if ($dataFlow->getValue() != null) { return; } $vars = SymbolUtils::getSymbolByNode($value); $dataFlow->setValue($vars); } }
/** * 处理赋值的assign语句,添加至dataFlows中 * @param AST $node * @param DataFlow $dataFlow * @param string $type */ public function assignHandler($node, $dataFlow, $type, $block, $fileSummary) { $part = null; if ($type == "left") { $part = $node->var; } else { if ($type == "right") { $part = $node->expr; } else { return; } } //处理$GLOBALS的赋值 //$GLOBAL['name'] = "chongrui" ; 数据流信息为 $name = "chongrui" ; if ($part && SymbolUtils::isArrayDimFetch($part) && substr(NodeUtils::getNodeStringName($part), 0, 7) == "GLOBALS") { //加入dataFlow $arr = new ArrayDimFetchSymbol(); $arr->setValue($part); if ($type == "left") { $dataFlow->setLocation($arr); $dataFlow->setName(NodeUtils::getNodeGLOBALSNodeName($part)); } else { if ($type == "right") { $dataFlow->setValue($arr); } } return; } //处理赋值语句,存放在DataFlow //处理赋值语句的左边 if ($part && SymbolUtils::isValue($part)) { //在DataFlow加入Location以及name $vs = new ValueSymbol(); $vs->setValueByNode($part); if ($type == "left") { $dataFlow->setLocation($vs); $dataFlow->setName($part->name); } else { if ($type == "right") { $dataFlow->setValue($vs); } } } elseif ($part && SymbolUtils::isVariable($part)) { //加入dataFlow $vars = new VariableSymbol(); $vars->setValue($part); if ($type == "left") { $dataFlow->setLocation($vars); $dataFlow->setName($part->name); } else { if ($type == "right") { $dataFlow->setValue($part); } } } elseif ($part && SymbolUtils::isConstant($part)) { //加入dataFlow $con = new ConstantSymbol(); $con->setValueByNode($part); $con->setName($part->name->parts[0]); if ($type == "left") { $dataFlow->setLocation($con); $dataFlow->setName($part->name); } else { if ($type == "right") { $dataFlow->setValue($con); } } } elseif ($part && SymbolUtils::isArrayDimFetch($part)) { //加入dataFlow $arr = new ArrayDimFetchSymbol(); $arr->setValue($part); if ($type == "left") { $dataFlow->setLocation($arr); $dataFlow->setName(NodeUtils::getNodeStringName($part)); } else { if ($type == "right") { $dataFlow->setValue($arr); } } } elseif ($part && SymbolUtils::isConcat($part)) { $concat = new ConcatSymbol(); $concat->setItemByNode($part); if ($type == "left") { $dataFlow->setLocation($concat); $dataFlow->setName($part->name); } else { if ($type == "right") { $dataFlow->setValue($concat); } } } else { //不属于已有的任何一个symbol类型,如函数调用 if ($part && ($part->getType() == "Expr_FuncCall" || $part->getType() == "Expr_MethodCall" || $part->getType() == "Expr_StaticCall")) { if ($type == "left") { $dataFlow->setLocation($arr); $dataFlow->setName(NodeUtils::getNodeStringName($part)); } else { if ($type == "right") { //处理净化信息和编码信息 SanitizationHandler::setSanitiInfo($part, $dataFlow, $block, $fileSummary); EncodingHandler::setEncodeInfo($part, $dataFlow, $block, $fileSummary); } } } //处理三元表达式 if ($part && $part->getType() == "Expr_Ternary") { BIFuncUtils::ternaryHandler($type, $part, $dataFlow); } } }
/** * 污点分析的函数 * @param BasicBlock $block 当前基本块 * @param Node $node 当前的函数调用node * @param string $argName 危险参数名 * @param FileSummary 当前文件摘要 */ public function analysis($block, $node, $argName, $fileSummary) { //传入变量本身就是source $varName = substr($argName, 0, strpos($argName, '[')); if (in_array($varName, $this->sourcesArr) || in_array($argName, $this->sourcesArr)) { //报告漏洞 $path = $fileSummary->getPath(); $type = TypeUtils::getTypeByFuncName(NodeUtils::getNodeFunctionName($node)); $this->report($path, $path, $node, $argName, $type); } else { $path = $fileSummary->getPath(); //获取前驱基本块集合并将当前基本量添加至列表 $this->getPrevBlocks($block); $block_list = $this->pathArr; array_push($block_list, $block); //多个基本块的处理 $this->pathArr = array(); $this->multiBlockHandler($block, $argName, $node, $fileSummary); $this->multiFileHandler($block, $argName, $node, $fileSummary); } }
public function leaveNode(Node $node) { array_push($this->strings, NodeUtils::getNodeStringName($node)); }
/** * 查找参数在参数列表的位置 * @param 参数 $paramName * @param 参数列表 $params * @return 参数位置 */ public function searchPos($paramName, $params) { $count = 0; foreach ($params as $param) { if (NodeUtils::getNodeStringName($param) == $paramName) { return $count; } $count++; } return -1; }
/** * return变量块内回溯 * @param 变量对象 $arg * @param 当前块 $block * @param flowNum 遍历过的flow数量 * @return array(),返回是否净化,净化类型是什么 */ public function sanitiTracebackBlock($arg, $block, $flowsNum = 0) { global $SECURES_TYPE_ALL; $flows = $block->getBlockSummary()->getDataFlowMap(); $argName = NodeUtils::getNodeStringName($arg); // 去掉分析过的$flow $temp = $flowsNum; while ($temp > 0) { array_pop($flows); $temp--; } //将块内数据流逆序,从后往前遍历 $flows = array_reverse($flows); foreach ($flows as $flow) { $flowsNum++; //trace back if ($flow->getName() == $argName) { //处理净化信息 $ret = $flow->getlocation()->getSanitization(); if ($ret) { $type = array(); foreach ($ret as $oneFunction) { $type = array_merge($type, $oneFunction->getSanitiType()); } return array(true, 'type' => $type); } //得到flow->getValue()的变量node //$sql = $a . $b ; => array($a,$b) if ($flow->getValue() instanceof ConcatSymbol) { $vars = $flow->getValue()->getItems(); } else { $vars = array($flow->getValue()); } $retarr = array(); foreach ($vars as $var) { $ret = $this->sanitiMultiBlockHandler($var, $block, $flowsNum); //有一个变量值未净化,就是整个未净化 if (!$ret[0]) { return array(false); } array_push($retarr, $ret['type']); } //统计变量值的净化信息,所有相关值被净化,且净化类型相同,则变量净化了该类型 $varsNum = count($vars); $retNum = count($retarr); if ($varsNum != $retNum) { return array(false); } $ret = $SECURES_TYPE_ALL; foreach ($retarr as $arr) { $ret = array_intersect($ret, $arr); } return array(true, 'type' => $ret); } } if ($arg instanceof ValueSymbol) { return array(true, 'type' => $SECURES_TYPE_ALL); } elseif ($arg instanceof Scalar) { return array(true, 'type' => $SECURES_TYPE_ALL); } return $this->sanitiMultiBlockHandler($arg, $block, $flowsNum); }
/** * sink单块回溯 * @param string $argName * @param BasicBlock $block * @param flowNum 遍历过的flow数量 * @return array */ public function sinkTracebackBlock($argName, $block, $flowsNum) { $flows = $block->getBlockSummary()->getDataFlowMap(); //需要将遍历过的dataflow删除 $temp = $flowsNum; while ($temp > 0) { array_pop($flows); $temp--; } //将块内数据流逆序,从后往前遍历 $flows = array_reverse($flows); foreach ($flows as $flow) { $flowsNum++; //trace back if ($flow->getName() == $argName) { //处理净化信息 if ($flow->getLocation()->getSanitization()) { return "safe"; } //得到flow->getValue()的变量node //$sql = $a . $b ; => array($a,$b) if ($flow->getValue() instanceof ConcatSymbol) { $vars = $flow->getValue()->getItems(); } else { $vars = array($flow->getValue()); } $retarr = array(); foreach ($vars as $var) { $var = NodeUtils::getNodeStringName($var); $ret = $this->sinkMultiBlockTraceback($var, $block, $flowsNum); //变量经过净化,这不需要跟踪该变量 if ($ret == "safe") { $retarr = array_slice($retarr, array_search($var, $retarr)); } else { $retarr = array_merge($ret, $retarr); } } return $retarr; } } if ($argName instanceof Node) { $argName = NodeUtils::getNodeStringName($argName); return array($argName); } return $this->sinkMultiBlockTraceback($argName, $block, $flowsNum); }
/** * 相同变量块内回溯 * @param 净化变量 $var * @param 数据流 $dataFlow * @return 是否净化,及净化信息 */ public static function encodeSameVarTraceback($varName, $block, $dataFlows) { global $F_ENCODING_STRING; //将块内数据流逆序,从后往前遍历 $flows = $dataFlows; foreach ($flows as $flow) { //需要将遍历过的dataflow删除 array_shift($dataFlows); //trace back if ($flow->getName() == $varName) { //处理净化信息 $ret = $flow->getlocation()->getEncoding(); if ($ret) { //存在净化,return return array(true, 'funcs' => $ret); } else { //没净化,继续回溯 //$sql = $a . $b ; => array($a,$b) $vars = array(); if ($flow->getValue() instanceof ConcatSymbol) { $vars = $flow->getValue()->getItems(); } else { $vars = array($flow->getValue()); } $retarr = array(); foreach ($vars as $var) { $varName = NodeUtils::getNodeStringName($var); $ret = self::encodeSameVarMultiBlockHandler($varName, $block, $dataFlows); if ($ret[0]) { $retarr = array_merge($retarr, $ret['funcs']); } else { return array(false); } } if ($retarr) { return array(true, 'funcs' => $retarr); } return array(false); } } } //当前块内不存在,回溯上一块 return self::encodeSameVarMultiBlockHandler($varName, $block, $dataFlows); }
/** * 通过node获取变量名称 * @param AST $node */ public function setNameByNode($node) { $this->name = NodeUtils::getNodeStringName($node); }