IDOR through request to backend service
Author: LGTM
import javascript
import DataFlow
import DataFlow::PathGraph
/**
* A taint-tracking configuration that 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
}
}
/**
* A sanitizer for values that have successfully 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"
Description
Finds cases where the 'userId' field in a request to another service is an arbitrary user-controlled value, indicating lack of authentication.