JS: Add SharedTaintStep

This commit is contained in:
Asger Feldthaus
2020-03-28 21:22:50 +00:00
parent 05779ef7ee
commit c3e00181cb
2 changed files with 46 additions and 20 deletions

View File

@@ -15,6 +15,7 @@
import javascript
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
private import semmle.javascript.dataflow.internal.Unit
private import semmle.javascript.dataflow.InferredTypes
private import semmle.javascript.internal.CachedStages
@@ -139,7 +140,7 @@ module TaintTracking {
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ) or
any(AdditionalTaintStep dts).step(pred, succ)
sharedTaintStep(pred, succ)
}
final override predicate isAdditionalFlowStep(
@@ -207,6 +208,33 @@ module TaintTracking {
override predicate sanitizes(boolean outcome, Expr e) { none() }
}
/**
* A taint-propagating data flow edge that should be added to all taint tracking
* configurations in addition to standard data flow edges.
*
* This class is a singleton, and thus subclasses do not need to specify a characteristic predicate.
*
* Note: For performance reasons, all subclasses of this class should be part
* of the standard library. Override `Configuration::isAdditionalTaintStep`
* for analysis-specific taint steps.
*/
class SharedTaintStep extends Unit {
/**
* Holds if `pred` → `succ` should be considered a taint-propagating
* data flow edge.
*/
abstract predicate step(DataFlow::Node pred, DataFlow::Node succ);
}
/**
* Holds if `pred -> succ` is an edge used by all taint-tracking configurations.
*/
cached predicate sharedTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
any(SharedTaintStep step).step(pred, succ)
or
any(AdditionalTaintStep step).step(pred, succ)
}
/**
* A taint-propagating data flow edge that should be added to all taint tracking
* configurations in addition to standard data flow edges.
@@ -215,13 +243,11 @@ module TaintTracking {
* of the standard library. Override `Configuration::isAdditionalTaintStep`
* for analysis-specific taint steps.
*/
cached
abstract class AdditionalTaintStep extends DataFlow::Node {
/**
* Holds if `pred` → `succ` should be considered a taint-propagating
* data flow edge.
*/
cached
abstract predicate step(DataFlow::Node pred, DataFlow::Node succ);
}
@@ -312,14 +338,12 @@ module TaintTracking {
/**
* A taint propagating data flow edge through persistent storage.
*/
class PersistentStorageTaintStep extends AdditionalTaintStep {
PersistentReadAccess read;
PersistentStorageTaintStep() { this = read }
class PersistentStorageTaintStep extends SharedTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = read.getAWrite().getValue() and
succ = read
exists(PersistentReadAccess read |
pred = read.getAWrite().getValue() and
succ = read
)
}
}
@@ -360,10 +384,8 @@ module TaintTracking {
* taint to flow from `v` to any read of `c2.state.p`, where `c2`
* also is an instance of `C`.
*/
private class ReactComponentStateTaintStep extends AdditionalTaintStep {
DataFlow::Node source;
ReactComponentStateTaintStep() {
private class ReactComponentStateTaintStep extends SharedTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ReactComponent c, DataFlow::PropRead prn, DataFlow::PropWrite pwn |
(
c.getACandidateStateSource().flowsTo(pwn.getBase()) or
@@ -375,14 +397,10 @@ module TaintTracking {
)
|
prn.getPropertyName() = pwn.getPropertyName() and
this = prn and
source = pwn.getRhs()
succ = prn and
pred = pwn.getRhs()
)
}
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = source and succ = this
}
}
/**

View File

@@ -0,0 +1,8 @@
private newtype TUnit = MkUnit()
/**
* A class with only one instance.
*/
class Unit extends TUnit {
final string toString() { result = "Unit" }
}