JS: Port ConditionalBypass

This commit is contained in:
Asger F
2023-10-05 09:13:00 +02:00
parent 2296a273c4
commit f14303acea
3 changed files with 130 additions and 114 deletions

View File

@@ -13,7 +13,28 @@ import ConditionalBypassCustomizations::ConditionalBypass
/**
* A taint tracking configuration for bypass of sensitive action guards.
*/
class Configuration extends TaintTracking::Configuration {
module ConditionalBypassConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node dst) {
// comparing a tainted expression against a constant gives a tainted result
dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c))
}
}
/**
* Taint tracking flow for bypass of sensitive action guards.
*/
module ConditionalBypassFlow = TaintTracking::Global<ConditionalBypassConfig>;
/**
* DEPRECATED. Use the `ConditionalBypassFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ConditionalBypass" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -26,8 +47,7 @@ class Configuration extends TaintTracking::Configuration {
}
override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) {
// comparing a tainted expression against a constant gives a tainted result
dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c))
ConditionalBypassConfig::isAdditionalFlowStep(src, dst)
}
}
@@ -72,7 +92,67 @@ class SensitiveActionGuardComparisonOperand extends Sink {
* If flow from `source` taints `sink`, then an attacker can
* control if `action` should be executed or not.
*/
predicate isTaintedGuardForSensitiveAction(
predicate isTaintedGuardNodeForSensitiveAction(
ConditionalBypassFlow::PathNode sink, ConditionalBypassFlow::PathNode source,
SensitiveAction action
) {
action = sink.getNode().(Sink).getAction() and
// exclude the intermediary sink
not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
(
// ordinary taint tracking to a guard
ConditionalBypassFlow::flowPath(source, sink)
or
// taint tracking to both operands of a guard comparison
exists(
SensitiveActionGuardComparison cmp, ConditionalBypassFlow::PathNode lSource,
ConditionalBypassFlow::PathNode rSource, ConditionalBypassFlow::PathNode lSink,
ConditionalBypassFlow::PathNode rSink
|
sink.getNode() = cmp.getGuard() and
ConditionalBypassFlow::flowPath(lSource, lSink) and
lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
ConditionalBypassFlow::flowPath(rSource, rSink) and
rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand())
|
source = lSource or
source = rSource
)
)
}
/**
* Holds if `e` effectively guards access to `action` by returning or throwing early.
*
* Example: `if (e) return; action(x)`.
*/
predicate isEarlyAbortGuardNode(ConditionalBypassFlow::PathNode e, SensitiveAction action) {
exists(IfStmt guard |
// `e` is in the condition of an if-statement ...
e.getNode().(Sink).asExpr().getParentExpr*() = guard.getCondition() and
// ... where the then-branch always throws or returns
exists(Stmt abort |
abort instanceof ThrowStmt or
abort instanceof ReturnStmt
|
abort.nestedIn(guard) and
abort.getBasicBlock().(ReachableBasicBlock).postDominates(guard.getThen().getBasicBlock())
) and
// ... and the else-branch does not exist
not exists(guard.getElse())
|
// ... and `action` is outside the if-statement
not action.asExpr().getEnclosingStmt().nestedIn(guard)
)
}
/**
* Holds if `sink` guards `action`, and `source` taints `sink`.
*
* If flow from `source` taints `sink`, then an attacker can
* control if `action` should be executed or not.
*/
deprecated predicate isTaintedGuardForSensitiveAction(
DataFlow::PathNode sink, DataFlow::PathNode source, SensitiveAction action
) {
action = sink.getNode().(Sink).getAction() and
@@ -104,7 +184,7 @@ predicate isTaintedGuardForSensitiveAction(
*
* Example: `if (e) return; action(x)`.
*/
predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
deprecated predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
exists(IfStmt guard |
// `e` is in the condition of an if-statement ...
e.getNode().(Sink).asExpr().getParentExpr*() = guard.getCondition() and