JS: Migrate HardcodedDataInterpretedAsCode

This commit is contained in:
Asger F
2024-12-13 10:48:43 +01:00
parent dc3d7a0159
commit 2112ecc44d
2 changed files with 50 additions and 15 deletions

View File

@@ -8,20 +8,57 @@ import javascript
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
module HardcodedDataInterpretedAsCode {
private newtype TFlowState =
TUnmodified() or
TModified()
/** A flow state to associate with a tracked value. */
class FlowState extends TFlowState {
/** Gets a string representation fo this flow state */
string toString() {
this = TUnmodified() and result = "unmodified"
or
this = TModified() and result = "modified"
}
deprecated DataFlow::FlowLabel toFlowLabel() {
this = TUnmodified() and result.isData()
or
this = TModified() and result.isTaint()
}
}
/** Predicates for working with flow states. */
module FlowState {
deprecated FlowState fromFlowLabel(DataFlow::FlowLabel label) { result.toFlowLabel() = label }
/** An unmodified value originating from a string constant. */
FlowState unmodified() { result = TUnmodified() }
/** A value which has undergone some transformation, such as hex decoding. */
FlowState modified() { result = TModified() }
}
/**
* A data flow source for hard-coded data.
*/
abstract class Source extends DataFlow::Node {
/** Gets a flow label for which this is a source. */
DataFlow::FlowLabel getLabel() { result.isData() }
/** Gets a flow state for which this is a source. */
FlowState getAFlowState() { result = FlowState::unmodified() }
/** DEPRECATED. Use `getAFlowState()` instead. */
deprecated DataFlow::FlowLabel getLabel() { result = this.getAFlowState().toFlowLabel() }
}
/**
* A data flow sink for code injection.
*/
abstract class Sink extends DataFlow::Node {
/** Gets a flow label for which this is a sink. */
abstract DataFlow::FlowLabel getLabel();
/** Gets a flow state for which this is a sink. */
FlowState getAFlowState() { result = FlowState::modified() }
/** DEPRECATED. Use `getAFlowState()` instead. */
deprecated DataFlow::FlowLabel getLabel() { result = this.getAFlowState().toFlowLabel() }
/** Gets a description of what kind of sink this is. */
abstract string getKind();
@@ -50,7 +87,7 @@ module HardcodedDataInterpretedAsCode {
* A code injection sink; hard-coded data should not flow here.
*/
private class DefaultCodeInjectionSink extends Sink instanceof CodeInjection::Sink {
override DataFlow::FlowLabel getLabel() { result.isTaint() }
override FlowState getAFlowState() { result = FlowState::modified() }
override string getKind() { result = "Code" }
}
@@ -61,7 +98,7 @@ module HardcodedDataInterpretedAsCode {
private class RequireArgumentSink extends Sink {
RequireArgumentSink() { this = any(Require r).getAnArgument().flow() }
override DataFlow::FlowLabel getLabel() { result.isDataOrTaint() }
override FlowState getAFlowState() { result = [FlowState::modified(), FlowState::unmodified()] }
override string getKind() { result = "An import path" }
}

View File

@@ -10,29 +10,27 @@
import javascript
import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode
private import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode as HardcodedDataInterpretedAsCode
/**
* A taint-tracking configuration for reasoning about hard-coded data
* being interpreted as code
*/
module HardcodedDataInterpretedAsCodeConfig implements DataFlow::StateConfigSig {
class FlowState = DataFlow::FlowLabel;
class FlowState = HardcodedDataInterpretedAsCode::FlowState;
predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
source.(Source).getLabel() = lbl
}
predicate isSource(DataFlow::Node source, FlowState lbl) { source.(Source).getAFlowState() = lbl }
predicate isSink(DataFlow::Node nd, DataFlow::FlowLabel lbl) { nd.(Sink).getLabel() = lbl }
predicate isSink(DataFlow::Node nd, FlowState lbl) { nd.(Sink).getAFlowState() = lbl }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowLabel state1, DataFlow::Node node2,
DataFlow::FlowLabel state2
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
TaintTracking::defaultTaintStep(node1, node2) and
state1.isDataOrTaint() and
state2.isTaint()
state1 = [FlowState::modified(), FlowState::unmodified()] and
state2 = FlowState::modified()
}
}