/**
  * 分离isset结构中的类型
  * isset($id) ? $_GET['id'] : 2;
  * 转为:
  * 		array($_GET[id],2)
  * @param unknown $node
  */
 public function setItemByNode($node)
 {
     //处理三元表达式
     if ($node->getType() == "Expr_Ternary") {
         if ($node->if->getType() == "Expr_Ternary") {
             $this->setItemByNode($node->if);
         }
         if ($node->else->getType() == "Expr_Ternary") {
             $this->setItemByNode($node->else);
         }
         $if_node = SymbolUtils::getSymbolByNode($node->if);
         $else_node = SymbolUtils::getSymbolByNode($node->else);
         $if_node && $this->addSymbol($if_node);
         $else_node && $this->addSymbol($else_node);
     } else {
         return;
     }
 }
 /**
  * 处理赋值性的一些内置函数
  * 比如:
  * 		$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);
         }
     }
 }
 /**
  * 根据sink的类型、危险参数的净化信息列表、编码列表
  * 判断是否是有效的净化
  * 返回:
  * 		(1)true		=>得到净化
  * 		(2)false	=>没有净化
  * 'XSS','SQLI','HTTP','CODE','EXEC','LDAP','INCLUDE','FILE','XPATH','FILEAFFECT'
  * @param string $type 漏洞的类型,使用TypeUtils可以获取
  * @param Symbol $var 危险参数
  * @param array $saniArr 危险参数的净化信息栈
  * @param array $encodingArr 危险参数的编码信息栈
  */
 public function isSanitization($type, $var, $saniArr_obj, $encodingArr)
 {
     //整理saniArr
     $saniArr = array();
     if (is_object($saniArr_obj)) {
         foreach ($saniArr_obj as $value) {
             array_push($saniArr, $value->funcName);
         }
     } else {
         $saniArr = $saniArr_obj;
     }
     $is_clean = null;
     $var_type = '';
     if ($var instanceof Node) {
         $var = SymbolUtils::getSymbolByNode($var);
     }
     if ($var instanceof ValueSymbol) {
         return true;
     }
     //如果symbol类型为int,直接返回安全true
     if (!in_array($var->getType(), array('string', 'valueInt'))) {
         return true;
     }
     //根据不同的漏洞类型进行判断
     switch ($type) {
         case 'SQLI':
             $sql_analyser = new SqliAnalyser();
             $is_clean = $sql_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'XSS':
             $xss_analyser = new XssAnalyser();
             $is_clean = $xss_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'HTTP':
             $http_analyser = new HeaderAnalyser();
             $is_clean = $http_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'CODE':
             $code_analyser = new CodeAnalyser();
             $is_clean = $code_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'EXEC':
             $exec_analyser = new ExecAnalyser();
             $is_clean = $exec_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'LDAP':
             $ldap_analyser = new LDPAAnalyser();
             $is_clean = $ldap_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'INCLUDE':
             $include_analyser = new IncludeAnalyser();
             $is_clean = $include_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'FILE':
             $file_analyser = new FileAnalyser();
             $is_clean = $file_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'XPATH':
             $xpath_analyser = new XPathAnalyser();
             $is_clean = $xpath_analyser->analyse($var, $saniArr, $encodingArr);
             break;
         case 'FILEAFFECT':
             $file_affect_analyser = new FileAffectAnalyser();
             $is_clean = $file_affect_analyser->analyse($var, $saniArr, $encodingArr);
             break;
     }
     return $is_clean;
 }
 /**
  * 获取函数的参数名称
  * @param Node $node 函数调用的node
  * @return array(arg1[,arg2,arg3,...])
  */
 public static function getNodeFuncParams($node)
 {
     if (!$node instanceof Node) {
         return null;
     }
     //支持echo和print
     $funcName = self::getNodeFunctionName($node);
     if ($funcName == "echo") {
         $ret = array();
         if ($node->exprs[0]->getType() == "Expr_BinaryOp_Concat") {
             $ret = self::getConcatParams($node->exprs[0]);
         } else {
             if (SymbolUtils::isValue($node->exprs[0])) {
                 return array();
             } else {
                 $res = self::getNodeStringName($node->exprs[0]);
                 if (is_array($res)) {
                     array_merge($ret, $res);
                 } else {
                     array_push($ret, $res);
                 }
             }
         }
         return $ret;
     } else {
         if ($funcName == 'include') {
             $ret = array();
             if ($node->expr->getType() == "Expr_BinaryOp_Concat") {
                 $ret = self::getConcatParams($node->expr);
             } elseif ($node->expr->getType() == "Scalar_Encapsed") {
                 $args = $node->expr->parts;
                 foreach ($args as $arg) {
                     if (SymbolUtils::isValue($arg)) {
                         continue;
                     } else {
                         array_push($ret, NodeUtils::getNodeStringName($arg));
                     }
                 }
             } else {
                 if (SymbolUtils::isValue($node->expr)) {
                     return array();
                 } else {
                     $ret = self::getNodeStringName($node->expr);
                 }
             }
             return $ret;
         } else {
             if ($funcName == "print") {
                 $ret = array();
                 if ($node->expr->getType() == "Expr_BinaryOp_Concat") {
                     $ret = self::getConcatParams($node->expr);
                 } else {
                     if (SymbolUtils::isValue($node->expr)) {
                         return array();
                     } else {
                         $ret = self::getNodeStringName($node->expr);
                     }
                 }
                 return $ret;
             } else {
                 if ($funcName == "eval") {
                     $ret = array();
                     if ($node->expr->getType() == "Expr_BinaryOp_Concat") {
                         $ret = self::getConcatParams($node->expr);
                     } else {
                         if (SymbolUtils::isValue($node->expr)) {
                             return array();
                         } else {
                             $ret = self::getNodeStringName($node->expr);
                         }
                     }
                     return $ret;
                 }
             }
         }
     }
     //处理其他的函数
     $argsArr = array();
     if ($node->args) {
         foreach ($node->args as $arg) {
             //如果为concat类型
             if ($arg->value->getType() == "Expr_BinaryOp_Concat") {
                 $concatArr = self::getConcatParams($arg->value);
                 array_push($argsArr, $concatArr);
             } else {
                 array_push($argsArr, NodeUtils::getNodeStringName($arg));
             }
         }
     } elseif ($node->params) {
         foreach ($node->params as $arg) {
             if ($arg->getType() == "Expr_BinaryOp_Concat") {
                 $concatArr = self::getConcatParams($arg->value);
                 array_push($argsArr, $concatArr);
             } else {
                 array_push($argsArr, NodeUtils::getNodeStringName($arg));
             }
         }
     }
     return $argsArr;
 }
 public function leaveNode(Node $node)
 {
     $type = $node->getType();
     if ($type == "Expr_BinaryOp_Concat") {
         if ($node->right) {
             //转为symbol
             $right_symbol = SymbolUtils::getSymbolByNode($node->right);
             $right_symbol != null && array_push($this->items, $right_symbol);
         }
         if ($node->left->getType() != "Expr_BinaryOp_Concat") {
             $left_symbol = SymbolUtils::getSymbolByNode($node->left);
             $left_symbol != null && array_push($this->items, $left_symbol);
         }
     } else {
         if ($type == "Scalar_Encapsed") {
             foreach ($node->parts as $item) {
                 if (!is_object($item)) {
                     $valueSymbol = new ValueSymbol();
                     $valueSymbol->setValue($item);
                     $valueSymbol != null && array_push($this->items, $valueSymbol);
                 } else {
                     $setItem = SymbolUtils::getSymbolByNode($item);
                     $setItem != null && array_push($this->items, $setItem);
                 }
             }
         }
     }
 }
 public function leaveNode(Node $node)
 {
     global $SECURES_TYPE_ALL;
     if (!$node instanceof Node) {
         return null;
     }
     if ($node->getType() == 'Stmt_Return') {
         $part = $node->expr;
         if (SymbolUtils::isValue($part)) {
             //return value
             if (!is_array($this->sanitiInfo['type'])) {
                 $this->sanitiInfo['type'] = array($this->sanitiInfo['type']);
             }
             $type = array_intersect($this->sanitiInfo['type'], $SECURES_TYPE_ALL);
             $this->sanitiInfo = array(true, 'type' => $type);
         } elseif (SymbolUtils::isVariable($part)) {
             //return variable
             $context = Context::getInstance();
             $funcBody = $context->getFunctionBody($this->funcName);
             if (!$funcBody) {
                 return null;
             }
             $nodes = $funcBody->stmts;
             $cfg = new CFGGenerator();
             $block = $cfg->CFGBuilder($nodes, NULL, NULL, NULL);
             $ret = $this->sanitiMultiBlockHandler($node->expr, $block);
             if ($ret[0]) {
                 $type = array_intersect($this->sanitiInfo['type'], $ret['type']);
                 $this->sanitiInfo = array(true, 'type' => $type);
             } else {
                 $this->sanitiInfo = null;
             }
         } elseif (SymbolUtils::isConstant($part)) {
             //return constant
             $type = array_intersect($this->sanitiInfo['type'], $SECURES_TYPE_ALL);
             $this->sanitiInfo = array(true, 'type' => $type);
         } elseif (SymbolUtils::isArrayDimFetch($part)) {
             //return array
             $context = Context::getInstance();
             $funcBody = $context->getFunctionBody($this->funcName);
             if (!$funcBody) {
                 return null;
             }
             $nodes = $funcBody->stmts;
             $cfg = new CFGGenerator();
             $block = $cfg->CFGBuilder($nodes, NULL, NULL, NULL);
             $ret = $this->sanitiMultiBlockHandler($node->expr, $block);
             if ($ret[0]) {
                 $type = array_intersect($this->sanitiInfo['type'], $ret['type']);
                 $this->sanitiInfo = array(true, 'type' => $type);
             } else {
                 $this->sanitiInfo = null;
             }
         } elseif (SymbolUtils::isConcat($part)) {
             //return concat
             $concat = new ConcatSymbol();
             $concat->setItemByNode($part);
             $items = $concat->getItems();
             if (!$items) {
                 return null;
             }
             $context = Context::getInstance();
             $funcBody = $context->getFunctionBody($this->funcName);
             if (!$funcBody) {
                 return null;
             }
             $nodes = $funcBody->stmts;
             $cfg = new CFGGenerator();
             $block = $cfg->CFGBuilder($nodes, NULL, NULL, NULL);
             $retarr = $SECURES_TYPE_ALL;
             foreach ($items as $item) {
                 $ret = $this->sanitiMultiBlockHandler($item, $block);
                 if ($ret[0]) {
                     $retarr = array_intersect($retarr, $ret['type']);
                 } else {
                     $this->sanitiInfo = array(false);
                     break;
                 }
             }
             $this->sanitiInfo = array(true, 'type' => $retarr);
         } else {
             //处理函数调用
             if ($part->getType() == 'Expr_FuncCall' || $part->getType() == 'Expr_MethodCall' || $part->getType() == 'Expr_StaticCall') {
                 $ret = SanitizationHandler::SantiniFuncHandler($part, $this->fileSummary);
                 if ($ret) {
                     $saniType = $ret->getSanitiType();
                     if (is_array($saniType[0])) {
                         $saniType = $saniType[0];
                     }
                     $type = array_intersect($this->sanitiInfo['type'], $saniType);
                     $this->sanitiInfo = array(true, 'type' => $type);
                 }
             }
         }
     } else {
         return null;
     }
 }
 /**
  * 根据AST node获取相应的symbol
  * @param unknown $node
  */
 public static function getSymbolByNode($node)
 {
     if ($node && SymbolUtils::isValue($node)) {
         //在DataFlow加入Location以及name
         $vs = new ValueSymbol();
         $vs->setValueByNode($node);
         return $vs;
     } elseif ($node && SymbolUtils::isVariable($node)) {
         //加入dataFlow
         $vars = new VariableSymbol();
         $vars->setNameByNode($node);
         $vars->setValue($node);
         return $vars;
     } elseif ($node && SymbolUtils::isArrayDimFetch($node)) {
         //加入dataFlow
         $arr = new ArrayDimFetchSymbol();
         $arr->setValue($node);
         return $arr;
     } elseif ($node && SymbolUtils::isConcat($node)) {
         $concat = new ConcatSymbol();
         $concat->setItemByNode($node);
         return $concat;
     } elseif ($node && $node->getType() == "Scalar_Encapsed") {
         $arr = array();
         $symbol = new MutipleSymbol();
         foreach ($node->parts as $item) {
             if (is_object($item) && self::isValue($item) == false) {
                 $sym = self::getSymbolByNode($item);
                 array_push($arr, $sym);
             }
         }
         $symbol->setSymbols($arr);
         return $symbol;
     } else {
         return null;
     }
 }
Example #9
0
 /**
  * 分析传入node赋值语句,以及当前block,
  * 生成block summary中的一条记录
  * @param ASTNode $node 赋值语句
  * @param BasicBlock $block
  * @param string $type 处理赋值语句的var和expr类型(left or right)
  */
 private function assignHandler($node, $block, $dataFlow, $type)
 {
     global $scan_type;
     $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));
             //加入registerglobal
             $this->registerGLOBALSHandler($part, $block);
         } 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);
         $arr->setNameByNode($node);
         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")) {
             //处理 id = urlencode($_GET['id']) ;
             if ($type == 'right' && !SymbolUtils::isValue($part)) {
                 $funcName = NodeUtils::getNodeFunctionName($part);
                 BIFuncUtils::assignFuncHandler($part, $type, $dataFlow, $funcName);
                 if ($dataFlow->getValue() != null) {
                     //如果处理完函数赋值,则立即返回
                     $block->getBlockSummary()->addDataFlowItem($dataFlow);
                     return;
                 } else {
                     //处理 id = urlencode($_GET['id']) ;
                     //检查是否为sink函数
                     $this->functionHandler($part, $block, $this->fileSummary);
                     //处理净化信息和编码信息
                     SanitizationHandler::setSanitiInfo($part, $dataFlow, $block, $this->fileSummary);
                     EncodingHandler::setEncodeInfo($part, $dataFlow, $block, $this->fileSummary);
                 }
             }
         }
         //处理类型强制转换
         if ($part && ($part->getType() == "Expr_Cast_Int" || $part->getType() == "Expr_Cast_Double") && $type == "right") {
             $dataFlow->getLocation()->setType("int");
             $symbol = SymbolUtils::getSymbolByNode($part->expr);
             $dataFlow->setValue($symbol);
         }
         //处理三元表达式
         if ($part && $part->getType() == "Expr_Ternary") {
             BIFuncUtils::ternaryHandler($type, $part, $dataFlow);
         }
         //处理双引号中包含的变量
         if ($part && $part->getType() == "Scalar_Encapsed") {
             $symbol = SymbolUtils::getSymbolByNode($part);
             $dataFlow->setValue($symbol);
         }
     }
     //else
     //处理完一条赋值语句,加入DataFlowMap
     if ($type == "right") {
         $block->getBlockSummary()->addDataFlowItem($dataFlow);
     }
 }