Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Published by Scroll Versions from space CBJS and version Publish

Finds cases where the 'userId' field in a request to another service is an arbitrary user-controlled value, indicating lack of authentication.

Ql
import javascript::
import DataFlow
import DataFlow::PathGraph

/**
 * Tracks user-controlled values into a 'userId' property sent to a backend service.
 */
class IdorTaint extends TaintTracking::Configuration {
  IdorTaint() { this = "IdorTaint" }

  override predicate isSource(Node node) { node instanceof RemoteFlowSource }

  override predicate isSink(Node node) { exists(ClientRequest req | node = req.getADataNode()) }

  override predicate isAdditionalTaintStep(Node pred, Node succ) {
    // Step from x -> { userId: x }
    succ.(SourceNode).getAPropertyWrite("userId").getRhs() = pred
  }

  override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) {
    // After a check like `if (userId === session.user.id)`, the userId is considered safe.
    node instanceof EqualityGuard
  }
}

/**
 * Sanitize values that have succesfully been compared to another value.
 */
class EqualityGuard extends TaintTracking::SanitizerGuardNode, ValueNode {
  override EqualityTest astNode;

  override predicate sanitizes(boolean outcome, Expr e) {
    e = astNode.getAnOperand() and
    outcome = astNode.getPolarity()
  }
}

from IdorTaint cfg, PathNode source, PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Unauthenticated user ID from $@.", source.getNode(), "here"
Htmlcomment
hiddentrue
hashconfluence_uploader_hash:72943db79af9ffa53dcdf647a5862e9c95c6bc15dc7d5ce3d7d58db929c1371dc9b3c6ac577c898e