mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
JavaScript: Teach PostMessageStar to reason about partially tainted objects.
This commit is contained in:
@@ -22,6 +22,20 @@ module PostMessageStar {
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A flow label representing an object with at least one tainted property.
|
||||
*/
|
||||
private class PartiallyTaintedObject extends DataFlow::FlowLabel {
|
||||
PartiallyTaintedObject() { this = "partially tainted object" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets either a standard flow label or the partial-taint label.
|
||||
*/
|
||||
private DataFlow::FlowLabel anyLabel() {
|
||||
result instanceof DataFlow::StandardFlowLabel or result instanceof PartiallyTaintedObject
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint tracking configuration for cross-window communication with unrestricted origin.
|
||||
*
|
||||
@@ -38,9 +52,38 @@ module PostMessageStar {
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
|
||||
sink instanceof Sink and lbl = anyLabel()
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
|
||||
) {
|
||||
// writing a tainted value to an object property makes the object partially tainted
|
||||
exists(DataFlow::PropWrite write |
|
||||
write.getRhs() = src and
|
||||
inlbl = anyLabel() and
|
||||
trg.(DataFlow::SourceNode).flowsTo(write.getBase()) and
|
||||
outlbl instanceof PartiallyTaintedObject
|
||||
)
|
||||
or
|
||||
// `toString` or `JSON.toString` on a partially tainted object gives a tainted value
|
||||
exists (DataFlow::InvokeNode toString | toString = trg |
|
||||
toString.(DataFlow::MethodCallNode).calls(src, "toString")
|
||||
or
|
||||
toString = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") and
|
||||
src = toString.getArgument(0)
|
||||
) and
|
||||
inlbl instanceof PartiallyTaintedObject and
|
||||
outlbl = DataFlow::FlowLabel::taint()
|
||||
or
|
||||
// `valueOf` preserves partial taint
|
||||
trg.(DataFlow::MethodCallNode).calls(src, "valueOf") and
|
||||
inlbl instanceof PartiallyTaintedObject and
|
||||
outlbl = inlbl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user