Skip to content

[Bug] Incomplete taint tracking for PHP applications #5710

@xywang18

Description

@xywang18

when running a simple demo, the taint engine fails to detect the flow from
$HTTP_GET_VARS['page'] to the first argument of echo:

<?php
function tep_href_link($page = '', $parameters = '') {
    if (tep_not_null($parameters)) { // bug here
        $link .= $parameters;
    }
    return $link;
}

function tep_not_null($value) {
   return false;
}

echo '<a href="' . tep_href_link("aaa", 'page=' . $HTTP_GET_VARS['page']) . '">';

after debugging, I found that the root cause seems to come from the interaction between TaskSolver and TaskCreator.:

// TaskSolver.scala 
      // Case 4: we have reached an argument to an internal method without semantic (output argument) and
      // this isn't the start node nor is it the argument for the parameter we just expanded => return partial result and stop traversing
      case arg: Expression
          if path.size > 1
            && arg.inCall.toList.exists(c => isCallToInternalMethodWithoutSemantic(c))
            && !arg.inCall.headOption.exists(x => isArgOrRetOfMethodWeCameFrom(x, path)) =>
        createPartialResultForOutputArgOrRet()
// TaskCreator.scala
    val forArgs = outArgsAndCalls.flatMap { case (result, args, path, callDepth) =>
      args.toList.flatMap {
        case arg: Expression =>
          // bug is introduced by this code
          val outParams = if (result.callSiteStack.nonEmpty) {
            List[MethodParameterOut]()
          } else {
            argToOutputParams(arg).l
          }
          outParams
            .filterNot(_.method.isExternal)
            .map { p =>
              val newStack =
                arg.inCall.headOption.map { x => x :: result.callSiteStack }.getOrElse(result.callSiteStack)
              ReachableByTask(result.taskStack :+ TaskFingerprint(p, newStack, callDepth + 1), path)
            }
        case _ => Vector.empty
      }
    }
val outParams = if (result.callSiteStack.nonEmpty) {
            List[MethodParameterOut]()
          } else {
            argToOutputParams(arg).l
          }

this check leads to return a empty task list

currently, I make a small modification to make this work well:

 val outParams = argToOutputParams(arg).l

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions