/scanner/Lib/VulnerabilityScanner.php
PHP | 2067 lines | 1765 code | 206 blank | 96 comment | 292 complexity | d91656c21398cac35237b507c2e4c9be MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0
Large files files are truncated, but you can click here to view the full file
- <?php
- $bodyTraverser = new PHPParser_NodeTraverser;
- class THAPS_PHPParser_Node_LoopExpanded extends PHPParser_NodeAbstract
- {
- public function __construct(array $items = array(), $line = -1, $docComment = null)
- {
- parent::__construct(
- array(
- 'items' => $items
- ),
- $line, $docComment
- );
- }
- }
- class THAPS_PHPParser_Node_SwitchExpanded extends PHPParser_NodeAbstract
- {
- public function __construct(array $cases = array(), $line = -1, $docComment = null)
- {
- parent::__construct(
- array(
- 'cases' => $cases
- ),
- $line, $docComment
- );
- }
- }
- class BodyVisitor extends PHPParser_NodeVisitorAbstract
- {
- /**
- * @var bool decides if full tree should be used, or equal branches should be removed.
- */
- private static $fullTree = false;
- public static function useFullTree($on)
- {
- self::$fullTree = $on;
- }
- private static $postCleanSQL = false;
- private static $postCleanXSS = false;
- private static $getCleanSQL = false;
- private static $getCleanXSS = false;
- private static $cookieCleanSQL = false;
- private static $cookieCleanXSS = false;
- private static $requestCleanSQL = false;
- private static $requestCleanXSS = false;
- public static function useCleanGetPost($sql, $xss)
- {
- self::$postCleanSQL = $sql;
- self::$postCleanXSS = $xss;
- self::$getCleanSQL = $sql;
- self::$getCleanXSS = $xss;
- self::$cookieCleanSQL = $sql;
- self::$cookieCleanXSS = $xss;
- self::$requestCleanSQL = $sql;
- self::$requestCleanXSS = $xss;
- }
- /**
- * @var int Defined how many times loops should be unrolled
- */
- private $loopExpandTimes = 1;
- public function setLoopExpandTimes($times)
- {
- $this->loopExpandTimes = $times;
- }
- /**
- * @var VulnerabilityStorage
- */
- public $vulnerabilities;
- public function setVulnerabilityStorage(VulnerabilityStorage &$vulnerabilities)
- {
- $this->vulnerabilities = $vulnerabilities;
- }
- public function getVulnerabilities()
- {
- return $this->vulnerabilities;
- }
- /**
- * @var VariableStorage
- */
- private $vScope;
- public function setVScope(VariableStorage $storage)
- {
- $this->vScope = $storage;
- }
- public function getVScope()
- {
- return $this->vScope;
- }
- /**
- * @var array
- */
- private $dependencies = null;
- public function setDependencies($deps)
- {
- $this->dependencies = $deps;
- }
- /**
- * @var VariableValue
- */
- private $taint;
- public function getTaint()
- {
- return $this->taint;
- }
- /**
- * When an if is left, this is used to determine if the scopes is unnessary.
- * @var VariableStorage[][]
- */
- private $ifScopes = array();
- public static $lastNode = -1;
- public function beforeTraverse(array $nodes)
- {
- if ($this->dependencies == null) {
- $this->dependencies = array();
- }
- $this->taint = new VariableValue();
- }
- public function afterTraverse(array $nodes)
- {
- return $this->vulnerabilities->get();
- }
- private static $ignoreProgress = false;
- public function enterNode(PHPParser_Node $node)
- {
- global $totalNodeCount, $stepSize;
- if ($node->getLine() == 143) {
- //echo "najs";
- }
- if (!self::$ignoreProgress && $node->getNodeNumber() != -1 && $node->getNodeNumber() % $stepSize == 0 && self::$lastNode != $node->getNodeNumber()) {
- echo "Progress @ " . date("H:i:s") . " - " . $node->getNodeNumber() . "/" . $totalNodeCount . "\n";
- self::$lastNode = $node->getNodeNumber();
- }
- /*
- * Control flow structures
- * Currently only IF/THEN/ELSE
- */
- if ($node instanceof PHPParser_Node_Stmt_If) {
- self::$ignoreProgress = true;
- // Create the new scopes for each if/elseif and else in the proper locatations
- $possiblePlaces = $this->vScope->getVariableValueConfigurations($this->dependencies);
- $this->ifScopes[] = $possiblePlaces;
- // Make accessment of condition, it might secure some variables
- $conditionVisitor = new ConditionVisitor();
- $conditionTranverser = new PHPParser_NodeTraverser();
- $conditionTranverser->addVisitor($conditionVisitor);
- $conditionTranverser->traverse(array($node->cond));
- $cleanVars = $conditionVisitor->getCleanedVars();
- foreach ($possiblePlaces as $possiblePlace) {
- $cond = $node->getFilename() . ":" . $node->getLine() . ":if (" . printNode($node->cond, true) . ")";
- // For each of the cleaned vars lets check if they are dangerous
- $storage = $possiblePlace->addSubstorage($cond);
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor;
- $taintVisitor->setVScope($storage);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- if (is_array($cleanVars))
- foreach ($cleanVars as $cleanVar) {
- $taintTraverser->traverse(array($cleanVar));
- $taint = $taintVisitor->getTaint();
- if ($taint instanceof VariableValue && $taint->userInput) {
- $taint->xss = false;
- $taint->sql = false;
- $taint->value = str_replace(array("_SQL", "_XSS"), "", $taint->value);
- $assignArray = $this->findVarNameAndDim($cleanVar, $taintTraverser, $taintVisitor);
- array_unshift($assignArray, $taint);
- call_user_func_array(array($storage, 'setVariableValue'), $assignArray);
- }
- }
- if ($node->elseifs !== null) {
- foreach ($node->elseifs as $elseif) {
- $cond = $elseif->getFilename() . ":" . $elseif->getLine() . ":elseif (" . printNode($elseif->cond, true) . ")";
- $storage = $possiblePlace->addSubstorage($cond);
- // Make accessment of condition, it might secure some variables
- $conditionVisitor = new ConditionVisitor();
- $conditionTranverser = new PHPParser_NodeTraverser();
- $conditionTranverser->addVisitor($conditionVisitor);
- $conditionTranverser->traverse(array($elseif->cond));
- $cleanVars = $conditionVisitor->getCleanedVars();
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor;
- $taintVisitor->setVScope($storage);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- if (is_array($cleanVars))
- foreach ($cleanVars as $cleanVar) {
- $taintTraverser->traverse(array($cleanVar));
- $taint = $taintVisitor->getTaint();
- if ($taint instanceof VariableValue && $taint->userInput) {
- $taint->xss = false;
- $taint->sql = false;
- $taint->value = str_replace(array("_SQL", "_XSS"), "", $taint->value);
- $assignArray = $this->findVarNameAndDim($cleanVar, $taintTraverser, $taintVisitor);
- array_unshift($assignArray, $taint);
- call_user_func_array(array($storage, 'setVariableValue'), $assignArray);
- }
- }
- }
- }
- if (($else = $node->else) !== null) {
- $cond = $else->getFilename() . ":" . $else->getLine() . ":else";
- $possiblePlace->addSubstorage($cond, true);
- }
- }
- // Set the current dependencies for the futher scan
- $this->dependencies[] = $node->getFilename() . ":" . $node->getLine() . ":if (" . printNode($node->cond, true) . ")";
- self::$ignoreProgress = false;
- }
- elseif ($node instanceof PHPParser_Node_Stmt_ElseIf) {
- // Pop the old dependency which will be the if or a prior elseif and add the elseif
- array_pop($this->dependencies);
- $this->dependencies[] = $node->getFilename() . ":" . $node->getLine() . ":elseif (" . printNode($node->cond, true) . ")";
- }
- elseif ($node instanceof PHPParser_Node_Stmt_Else) {
- // Pop the old dependency which will be the if or an elseif and add the else
- array_pop($this->dependencies);
- $this->dependencies[] = $node->getFilename() . ":" . $node->getLine() . ":else";
- }
- elseif ($node instanceof PHPParser_Node_Stmt_Switch) {
- $possiblePlaces = $this->vScope->getVariableValueConfigurations($this->dependencies);
- $this->ifScopes[] = $possiblePlaces;
- $remove = array();
- $merge = array();
- $concat = array();
- $default = false;
- foreach ($node->cases as $index => $case) {
- //
- if (count($case->stmts) == 0) {
- $merge[] = $case;
- $remove[] = $index;
- if ($case->cond == null) {
- $case->cond = new PHPParser_Node_Scalar_String("__default__", $case->getLine(), $case->getFilename(), $case->getDocComment());
- $default = true;
- }
- }
- else if ($case->stmts[count($case->stmts) - 1] instanceof PHPParser_Node_Stmt_Break) {
- /**
- * add stmts to earliers cases without break;
- */
- if (count($concat) > 0) {
- foreach ($concat as $tmpcase) {
- $tmpcase->stmts = array_merge($tmpcase->stmts, unserialize(serialize($case->stmts)));
- }
- $concat = array();
- }
- if ($case->cond == null) {
- $case->cond = new PHPParser_Node_Scalar_String("__default__", $case->getLine(), $case->getFilename(), $case->getDocComment());
- $default = true;
- }
- /**
- * Merge empty
- */
- if (count($merge) > 0) {
- foreach ($merge as $tmpcase) {
- $case->cond = new PHPParser_Node_Expr_LogicalOr($tmpcase->cond, $case->cond, $tmpcase->getLine(), $tmpcase->getFilename(), $tmpcase->getDocComment());
- }
- $merge = array();
- }
- $cond = $case->getFilename() . ":" . $case->getLine() . ":case " . printNode($case->cond, true);
- foreach ($possiblePlaces as $possiblePlace) {
- $possiblePlace->addSubstorage($cond, $default);
- }
- } else {
- $concat[] = $case;
- if ($case->cond == null) {
- $case->cond = new PHPParser_Node_Scalar_String("__default__", $case->getLine(), $case->getFilename(), $case->getDocComment());
- $default = true;
- }
- $cond = $case->getFilename() . ":" . $case->getLine() . ":case " . printNode($case->cond, true);
- foreach ($possiblePlaces as $possiblePlace) {
- $possiblePlace->addSubstorage($cond, $default);
- }
- }
- }
- foreach ($remove as $index) {
- array_splice($node->cases, $index, 1);
- }
- // Add empty dependency to remove at first case
- $this->dependencies[] = "FAKE FOR SWITCH CASE";
- }
- elseif ($node instanceof PHPParser_Node_Stmt_Case) {
- array_pop($this->dependencies);
- $cond = $node->getFilename() . ":" . $node->getLine() . ":case " . printNode($node->cond, true);
- $this->dependencies[] = $cond;
- }
- elseif ($node instanceof PHPParser_Node_Stmt_For) {
- // Expand the for loop
- $nodes = array_merge($node->init, $node->stmts, $node->loop);
- for ($i = 1; $i < $this->loopExpandTimes; $i++) {
- $nodes = array_merge($nodes, $node->stmts);
- $nodes = array_merge($nodes, $node->loop);
- }
- $tmp = new THAPS_PHPParser_Node_LoopExpanded($nodes, $node->getLine(), $node->getFilename(), $node->getDocComment());
- return $tmp;
- }
- elseif ($node instanceof PHPParser_Node_Stmt_While) {
- // Expand the while loop
- $nodes = $node->stmts;
- for ($i = 1; $i < $this->loopExpandTimes; $i++) {
- $nodes = array_merge($nodes, $node->stmts);
- }
- $tmp = new THAPS_PHPParser_Node_LoopExpanded($nodes, $node->getLine(), $node->getFilename(), $node->getDocComment());
- return $tmp;
- }
- elseif ($node instanceof PHPParser_Node_Stmt_Foreach) {
- // Lets detect if the foreach is a specific clean for
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor;
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($node->expr));
- $varTaint = $taintVisitor->getTaint();
- // might be an array - we only care for the first value, it might be dangerous
- while (is_array($varTaint)) {
- $varTaint = array_pop($varTaint);
- }
- //
- // Detech foreach (..$_POST/GET.. ) $_POST/GET = ...
- //
- if ($varTaint instanceof VariableValue && $varTaint->userInput && count($varTaint->flowpath) == 0 &&
- count($node->stmts) == 1 && $node->stmts[0] instanceof PHPParser_Node_Expr_Assign && $node->stmts[0]->var instanceof PHPParser_Node_Expr_ArrayDimFetch &&
- ($node->stmts[0]->var->var->name == "_POST" || $node->stmts[0]->var->var->name == "_GET" || $node->stmts[0]->var->var->name == "_COOKIE" || $node->stmts[0]->var->var->name == "_REQUEST")
- ) {
- $funcCallTraverser = new PHPParser_NodeTraverser();
- $funcCallVisitor = new FunctionCallResolver();
- $funcCallTraverser->addVisitor($funcCallVisitor);
- $funcCallTraverser->traverse($node->stmts);
- global $SECURING_ALL, $SECURING_XSS, $SECURING_SQL;
- $all = count(array_intersect($SECURING_ALL, $funcCallVisitor->getFuncCallList())) != 0;
- $xss = count(array_intersect($SECURING_XSS, $funcCallVisitor->getFuncCallList())) != 0;
- $sql = count(array_intersect($SECURING_SQL, $funcCallVisitor->getFuncCallList())) != 0;
- if ($node->stmts[0]->var->var->name == "_POST") {
- if ($sql || $all) {
- self::$postCleanSQL = true;
- }
- if ($xss || $all) {
- self::$postCleanXSS = true;
- }
- } else if ($node->stmts[0]->var->var->name == "_GET") {
- if ($sql || $all) {
- self::$getCleanSQL = true;
- }
- if ($xss || $all) {
- self::$getCleanXSS = true;
- }
- } else if ($node->stmts[0]->var->var->name == "_COOKIE") {
- if ($sql || $all) {
- self::$cookieCleanSQL = true;
- }
- if ($xss || $all) {
- self::$cookieCleanXSS = true;
- }
- } else if ($node->stmts[0]->var->var->name == "_REQUEST") {
- if ($sql || $all) {
- self::$requestCleanSQL = true;
- }
- if ($xss || $all) {
- self::$requestCleanXSS = true;
- }
- }
- return false;
- } else {
- // TODO: expand the foreach loop
- }
- }
- /**
- * Remove the boolean expr, as they do the same stuff, nothing
- */
- elseif ($node instanceof PHPParser_Node_Expr_Equal ||
- $node instanceof PHPParser_Node_Expr_NotEqual ||
- $node instanceof PHPParser_Node_Expr_Greater ||
- $node instanceof PHPParser_Node_Expr_GreaterOrEqual ||
- $node instanceof PHPParser_Node_Expr_Smaller ||
- $node instanceof PHPParser_Node_Expr_SmallerOrEqual ||
- $node instanceof PHPParser_Node_Expr_BooleanAnd ||
- $node instanceof PHPParser_Node_Expr_BooleanNot ||
- $node instanceof PHPParser_Node_Expr_BooleanOr ||
- $node instanceof PHPParser_Node_Expr_Identical
- ) {
- $this->taint = new VariableValue();
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_LogicalOr ||
- $node instanceof PHPParser_Node_Expr_LogicalAnd ||
- $node instanceof PHPParser_Node_Expr_LogicalXor
- ) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($node->left));
- $leftTaint = $taintVisitor->getTaint();
- $taintTraverser->traverse(array($node->right));
- $rightTaint = $taintVisitor->getTaint();
- $this->taint = new VariableValue();
- if ($leftTaint === null && $rightTaint !== null) {
- $this->taint = $rightTaint;
- } elseif ($leftTaint !== null && $rightTaint === null) {
- $this->taint = $leftTaint;
- } elseif ($leftTaint !== null && $rightTaint !== null) {
- if ($leftTaint instanceof VariableValue && $rightTaint instanceof VariableValue) {
- $this->taint->userInput = $leftTaint->userInput || $rightTaint->userInput;
- $this->taint->xss = $leftTaint->xss || $rightTaint->xss;
- $this->taint->sql = $leftTaint->sql || $rightTaint->sql;
- } else {
- // This is wrong, need to be better if left and right are complex
- $this->taint = $leftTaint;
- }
- }
- return false;
- }
- /**
- * INT, BOOL and DOUBLE casts makes value safe
- */
- elseif ($node instanceof PHPParser_Node_Expr_Cast_Bool ||
- $node instanceof PHPParser_Node_Expr_Cast_Double ||
- $node instanceof PHPParser_Node_Expr_Cast_Int
- ) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor;
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($node->expr));
- $varTaint = $taintVisitor->getTaint();
- $this->taint = new VariableValue();
- $this->taint->value = str_replace(array("USERINPUT", "_XSS", "_SQL"), array("USERCASTEDINPUT", "", ""), $varTaint->value);
- return false;
- }
- /**
- * Get variable values - these should only be hit where the vScope is a single target,
- * as they are a part of the taint evaluation - maybe that is ;)
- * - Torben
- */
- elseif ($node instanceof PHPParser_Node_Expr_Variable) {
- $val = $this->vScope->getVariableValue($node->name);
- if ($val !== null) {
- $this->taint = $val;
- } else if ($node->name == "_POST") {
- $var = new VariableValue();
- $var->userInput = true;
- $var->xss = self::$postCleanXSS;
- $var->sql = self::$postCleanSQL;
- $this->taint = array($var);
- } else if ($node->name == "_GET") {
- $var = new VariableValue();
- $var->userInput = true;
- $var->xss = self::$getCleanXSS;
- $var->sql = self::$getCleanSQL;
- $this->taint = array($var);
- } else if ($node->name == "_COOKIE") {
- $var = new VariableValue();
- $var->userInput = true;
- $var->xss = self::$cookieCleanXSS;
- $var->sql = self::$cookieCleanSQL;
- $this->taint = array($var);
- } else if ($node->name == "_REQUEST") {
- $var = new VariableValue();
- $var->userInput = true;
- $var->xss = self::$requestCleanXSS;
- $var->sql = self::$requestCleanSQL;
- $this->taint = array($var);
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_ArrayDimFetch) {
- // Find the value of an array dim fetch
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor;
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($node->dim));
- $dimVal = $taintVisitor->getTaint()->value;
- $dim = array($dimVal);
- $target = $node;
- // If multidimension is hit
- while ($target->var instanceof PHPParser_Node_Expr_ArrayDimFetch) {
- $target = $target->var;
- $taintTraverser->traverse(array($target->dim));
- $dimVal = $taintVisitor->getTaint()->value;
- array_unshift($dim, $dimVal);
- }
- array_unshift($dim, $target->var->name);
- $val = call_user_func_array(array($this->vScope, 'getVariableValue'), $dim);
- if ($val !== null) {
- $this->taint = $val;
- } else if ($target->var->name == "_POST") {
- // If the value is not found and we are talking POST or GET variables then "invent" them
- $this->taint->userInput = true;
- $this->taint->value = "{USERINPUT" . (self::$postCleanSQL ? "" : "_SQL") . (self::$postCleanXSS ? "" : "_XSS") . "}";
- $this->taint->xss = !self::$postCleanXSS;
- $this->taint->sql = !self::$postCleanSQL;
- } else if ($target->var->name == "_GET") {
- $this->taint->userInput = true;
- $this->taint->value = "{USERINPUT" . (self::$getCleanSQL ? "" : "_SQL") . (self::$getCleanXSS ? "" : "_XSS") . "}";
- $this->taint->xss = !self::$getCleanXSS;
- $this->taint->sql = !self::$getCleanSQL;
- } else if ($target->var->name == "_COOKIE") {
- $this->taint->userInput = true;
- $this->taint->value = "{USERINPUT" . (self::$cookieCleanSQL ? "" : "_SQL") . (self::$cookieCleanXSS ? "" : "_XSS") . "}";
- $this->taint->xss = !self::$cookieCleanXSS;
- $this->taint->sql = !self::$cookieCleanSQL;
- } else if ($target->var->name == "_REQUEST") {
- $this->taint->userInput = true;
- $this->taint->value = "{USERINPUT" . (self::$requestCleanSQL ? "" : "_SQL") . (self::$requestCleanXSS ? "" : "_XSS") . "}";
- $this->taint->xss = !self::$requestCleanXSS;
- $this->taint->sql = !self::$requestCleanSQL;
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_PropertyFetch) {
- // Get a property of an object
- $class = $this->vScope->getVariableValue($node->var->name);
- if (!($class instanceof ClassDescription)) {
- return false;
- }
- $property = $class->getProperty($node->name);
- if ($property !== null) {
- $this->taint = $this->vScope->getVariableValue($node->var->name, $node->name);
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_StaticPropertyFetch) {
- // Static variables are saved on class name level
- $this->taint = $this->vScope->getVariableValue(VAR_REP_STATIC . $node->class->parts[0], $node->name);
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_ClassConstFetch) {
- $className = $node->class->parts[0];
- $name = $node->name;
- if ($className == "self") {
- global $parsedClass;
- $className = $parsedClass;
- }
- if (($class = ClassStorage::getClass($className)) !== null) {
- if (isset($class->constants[$name])) {
- $this->taint = new VariableValue();
- $this->taint->value = $class->constants[$name]->value;
- }
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_ConstFetch) {
- $target = $this->vScope;
- while ($target->parentScope !== null) {
- $target = $target->parentScope;
- }
- if (defined(end($node->name->parts))) {
- $this->taint = new VariableValue();
- eval('$this->taint->value=' . end($node->name->parts) . ';');
- } else {
- $this->taint = $target->getVariableValue(VAR_REP_CONST . end($node->name->parts));
- if ($this->taint === null) {
- // Constants that are not defined are apparently defaulted to a string
- $this->taint = new VariableValue();
- $this->taint->value = end($node->name->parts);
- }
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_Concat) {
- // Concat, simple taint traverse both sides and .. concat.
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($node->left));
- $leftTaint = $taintVisitor->getTaint();
- $taintTraverser->traverse(array($node->right));
- $partTaint = $taintVisitor->getTaint();
- $this->taint->userInput = $leftTaint->userInput || $partTaint->userInput;
- $this->taint->xss = $leftTaint->xss || $partTaint->xss;
- $this->taint->sql = $leftTaint->sql || $partTaint->sql;
- if ($this->taint->userInput) {
- if ($leftTaint->userInput && !$partTaint->userInput) {
- $this->taint->flowpath = $leftTaint->flowpath;
- $this->taint->dependencies = $leftTaint->dependencies;
- } else if (!$leftTaint->userInput) {
- $this->taint->flowpath = $partTaint->flowpath;
- $this->taint->dependencies = $partTaint->dependencies;
- } else {
- $this->taint->flowpath = array_merge($leftTaint->flowpath, $partTaint->flowpath);
- $this->taint->dependencies = array_merge($leftTaint->dependencies, $partTaint->dependencies);
- }
- }
- $this->taint->value = $leftTaint->value . $partTaint->value;
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Scalar_Encapsed) {
- // String with included variables - i.e. "hello $name"
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- for ($i = 0; $i < count($node->parts); $i++) {
- if ($node->parts[$i] instanceof PHPParser_Node) {
- $taintTraverser->traverse(array($node->parts[$i]));
- $partTaint = $taintVisitor->getTaint();
- $old = $this->taint->userInput;
- $this->taint->userInput = $this->taint->userInput || $partTaint->userInput;
- $this->taint->xss = $this->taint->xss || $partTaint->xss;
- $this->taint->sql = $this->taint->sql || $partTaint->sql;
- if ($this->taint->userInput) {
- if (!$old) {
- $this->taint->flowpath = $partTaint->flowpath;
- $this->taint->dependencies = $partTaint->dependencies;
- } else {
- $this->taint->flowpath = array_merge($this->taint->flowpath, $partTaint->flowpath);
- $this->taint->dependencies = array_merge($this->taint->dependencies, $partTaint->dependencies);
- }
- }
- $this->taint->value = $this->taint->value . $partTaint->value;
- } else {
- $this->taint->value = $this->taint->value . $node->parts[$i];
- }
- }
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Scalar_FileConst) {
- $this->taint->value = $node->getFilename();
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Scalar_String ||
- $node instanceof PHPParser_Node_Scalar_LNumber
- ) {
- $this->taint->value = $node->value;
- return false;
- }
- elseif ($node instanceof PHPParser_Node_Expr_Array) {
- $array = array();
- foreach ($node->items as $item) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $taintTraverser->traverse(array($item->value));
- $val = $taintVisitor->getTaint();
- if ($item->key !== null) {
- $taintTraverser->traverse(array($item->key));
- $key = $taintVisitor->getTaint()->value;
- $array[$key] = $val;
- } else {
- $array[] = $val;
- }
- }
- $this->taint = $array;
- return false;
- }
- /**
- * Function and method calls
- */
- elseif ($node instanceof PHPParser_Node_Expr_FuncCall) {
- global $functions;
- $funcName = $node->name->parts[0];
- global $SECURING_ALL, $SECURING_XSS, $SECURING_SQL, $INSECURING_USERINPUT;
- if (in_array($funcName, $SECURING_XSS)) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- foreach ($args as $nr => $arg) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($arg->value));
- $this->taint = $taintVisitor->getTaint();
- }
- }
- $this->taint->xss = false;
- $this->taint->value = str_replace("_XSS", "", $this->taint->value);
- } else if (in_array($funcName, $SECURING_SQL)) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- foreach ($args as $nr => $arg) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($arg->value));
- $this->taint = $taintVisitor->getTaint();
- }
- }
- $this->taint->sql = false; //$oldTaint->sql;
- $this->taint->value = str_replace("_SQL", "", $this->taint->value);
- } else if (in_array($funcName, $SECURING_ALL)) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- foreach ($args as $nr => $arg) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($arg->value));
- $this->taint = $taintVisitor->getTaint();
- }
- }
- if ($this->taint instanceof VariableValue) {
- $this->taint->xss = false; //$oldTaint->xss;
- $this->taint->sql = false; //$oldTaint->sql;
- $this->taint->value = str_replace("_SQL", "", $this->taint->value);
- $this->taint->value = str_replace("_XSS", "", $this->taint->value);
- } else {
- $this->taint = new VariableValue();
- }
- } else if (in_array($funcName, $INSECURING_USERINPUT)) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- foreach ($args as $nr => $arg) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($arg->value));
- $this->taint = $taintVisitor->getTaint();
- }
- }
- if ($this->taint->userInput) {
- $this->taint->xss = true;
- $this->taint->sql = true;
- $this->taint->value = str_replace("{USERINPUT", "{USERINPUT_XSS", $this->taint->value);
- $this->taint->value = str_replace("{USERINPUT", "{USERINPUT_SQL", $this->taint->value);
- }
- } elseif (isset($functions[$funcName])) {
- $function = $functions[$funcName];
- $this->taint->userInput = false;
- $this->taint->xss = false;
- $this->taint->sql = false;
- if (count($function->returnAlwaysVulnerable) > 0) {
- foreach ($function->returnAlwaysVulnerable as $vuln) {
- if ($vuln->xss) {
- $this->taint->xss = true;
- $this->taint->userInput = true;
- }
- if ($vuln->sql) {
- $this->taint->sql = true;
- $this->taint->userInput = true;
- }
- if ($vuln->xss || $vuln->sql) {
- $this->taint->flowpath = array_merge($this->taint->flowpath, $vuln->flowpath);
- $this->taint->dependencies = array_merge($this->taint->dependencies, $vuln->dependencies);
- }
- }
- }
- if (count($function->alwaysVulnerable) > 0) {
- foreach ($function->alwaysVulnerable as $toCloneVuln) {
- $vuln = clone $toCloneVuln;
- $vuln->flowpath = array_merge($vuln->flowpath, array(printNode($node)));
- $vuln->dependencies = array_merge($vuln->dependencies, $this->dependencies);
- $this->vulnerabilities->add($vuln);
- }
- }
- if (count($function->globalVulnerable) > 0) {
- foreach ($function->globalVulnerable as $global => $vulns) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $tmpTaint = $varValueConfiguration->getVariableValue($global);
- if ($tmpTaint !== null) {
- foreach ($vulns as $vuln) {
- if ($tmpTaint->xss && $vuln->xss ||
- $tmpTaint->sql && $vuln->sql
- ) {
- $vuln->flowpath = array_merge($vuln->flowpath, array(printNode($node)), $tmpTaint->flowpath);
- $vuln->dependencies = array_merge($vuln->dependencies, $tmpTaint->dependencies);
- $this->vulnerabilities->add($vuln);
- }
- }
- }
- }
- }
- }
- if (count($function->returnGlobalVulnerable) > 0) {
- foreach ($function->returnGlobalVulnerable as $global => $vulns) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $tmpTaint = $varValueConfiguration->getVariableValue($global);
- if ($tmpTaint !== null) {
- foreach ($vulns as $vuln) {
- if ($tmpTaint->xss && $vuln->xss) {
- $this->taint->xss = true;
- $this->taint->userInput = true;
- }
- if ($tmpTaint->sql && $vuln->sql) {
- $this->taint->sql = true;
- $this->taint->userInput = true;
- }
- if (($tmpTaint->xss && $vuln->xss) || ($tmpTaint->sql && $vuln->sql)) {
- $this->taint->flowpath = array_merge($this->taint->flowpath, $vuln->flowpath, $tmpTaint->flowpath);
- $this->taint->dependencies = array_merge($this->taint->dependencies, $vuln->dependencies, $tmpTaint->dependencies);
- }
- }
- }
- }
- }
- }
- if (count($function->globalSideEffectAlways) > 0) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- foreach ($function->globalSideEffectAlways as $global => $taint) {
- $varValueConfiguration->setVariableValue($taint, $global);
- }
- }
- }
- if (count($function->vulnerableParameters) > 0 ||
- count($function->returnVulnerableParameters) > 0 ||
- count($function->globalSideEffectParameter) > 0
- ) {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- foreach ($args as $nr => $arg) {
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($arg->value));
- $taintInfo = $taintVisitor->getTaint();
- if (isset($function->vulnerableParameters[$nr])) {
- foreach ($function->vulnerableParameters[$nr] as $vulnParm) {
- if (($taintInfo->xss && $vulnParm->xss) || ($taintInfo->sql && $vulnParm->sql)) {
- $vulnParm->flowpath = array_merge($vulnParm->flowpath, array(printNode($node)), $taintInfo->flowpath);
- $vulnParm->dependencies = array_merge($vulnParm->dependencies, $taintInfo->dependencies);
- $this->vulnerabilities->add($vulnParm);
- }
- elseif ($vulnParm->sql && $taintInfo->userInput) {
- if (substr($taintInfo, 0, 1) !== "{" &&
- substr($taintInfo, -1) !== "}" &&
- preg_match_all("/(.*){USERINPUT[_XSQL]+}/mUs", $taintInfo->value, $matches) > 0
- ) {
- $acc = 0;
- foreach ($matches[1] as $match) {
- $acc += substr_count($match, "'");
- $acc += substr_count($match, '"');
- if ($acc % 2 == 0) {
- array_unshift($taintInfo->flowpath, printNode($node));
- $taintInfo->dependencies = array_merge($this->dependencies, $taintInfo->dependencies);
- $vulnerability = new VulnerabilityDescription();
- $vulnerability->sql = true;
- $vulnerability->flowpath = $taintInfo->flowpath;
- $vulnerability->dependencies = $taintInfo->dependencies;
- $vulnerability->description = "SQL VULNERABILITY FOUND AT mysql_query WITH MISSING QUOTING IN FILE " . $node->getFilename() . " LINE " . $node->getLine();
- $this->vulnerabilities->add($vulnerability);
- }
- }
- }
- }
- }
- }
- if (isset($function->returnVulnerableParameters[$nr])) {
- foreach ($function->returnVulnerableParameters[$nr] as $vulnParm) {
- if ($taintInfo->xss && $vulnParm->xss) {
- $this->taint->xss = true;
- $this->taint->userInput = true;
- }
- if ($taintInfo->sql && $vulnParm->sql) {
- $this->taint->sql = true;
- $this->taint->userInput = true;
- }
- if (($taintInfo->xss && $vulnParm->xss) || ($taintInfo->sql && $vulnParm->sql)) {
- $this->taint->flowpath = array_merge($this->taint->flowpath, $taintInfo->flowpath, $vulnParm->flowpath);
- $this->taint->dependencies = array_merge($this->taint->dependencies, $vulnParm->dependencies, $taintInfo->dependencies);
- }
- }
- }
- if (isset($function->globalSideEffectParameter[$nr])) {
- foreach ($function->globalSideEffectParameter[$nr] as $global => $parmTaint) {
- if ($taintInfo->xss || $taintInfo->sql || $taintInfo->userInput) {
- $varValueConfiguration->setVariableValue($parmTaint, $global);
- $parmTaint->flowpath = array_merge($parmTaint->flowpath, $taintInfo->flowpath, array(printNode($node)));
- $parmTaint->dependencies = array_merge($parmTaint->dependencies, $taintInfo->dependencies);
- }
- }
- }
- }
- }
- }
- } else if ($funcName == "dirname") {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations as $varValueConfiguration) {
- $taintVisitor->setVScope($varValueConfiguration);
- $taintTraverser->traverse(array($args[0]->value));
- $taintInfo = $taintVisitor->getTaint();
- $this->taint->value = dirname($taintInfo->value);
- }
- } else if ($funcName == "array_keys") {
- $taintTraverser = new PHPParser_NodeTraverser;
- $taintVisitor = new BodyVisitor();
- $taintVisitor->setVScope($this->vScope);
- $taintVisitor->setDependencies($this->dependencies);
- $taintVisitor->setVulnerabilityStorage($this->vulnerabilities);
- $taintTraverser->addVisitor($taintVisitor);
- $args = $node->args;
- $varValueConfigurations = $this->vScope->getVariableValueConfigurations($this->dependencies);
- foreach ($varValueConfigurations a…
Large files files are truncated, but you can click here to view the full file