コード例 #1
0
ファイル: NamedNodeImpl.php プロジェクト: guitarmarx/Saft
 /**
  * @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;
 }
コード例 #2
0
 /**
  * 处理赋值性的一些内置函数
  * 比如:
  * 		$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);
     }
 }
コード例 #3
0
 /**
  * 处理赋值的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);
         }
     }
 }
コード例 #4
0
 /**
  * 污点分析的函数
  * @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);
     }
 }
コード例 #5
0
 public function leaveNode(Node $node)
 {
     array_push($this->strings, NodeUtils::getNodeStringName($node));
 }
コード例 #6
0
 /**
  * 查找参数在参数列表的位置
  * @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;
 }
コード例 #7
0
 /**
  * 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);
 }
コード例 #8
0
 /**
  * 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);
 }
コード例 #9
0
 /**
  * 相同变量块内回溯
  * @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);
 }
コード例 #10
0
 /**
  * 通过node获取变量名称
  * @param AST $node
  */
 public function setNameByNode($node)
 {
     $this->name = NodeUtils::getNodeStringName($node);
 }