Python: Some renaming of flow states

This commit is contained in:
Rasmus Lerchedahl Petersen
2023-09-28 14:24:49 +02:00
parent d5b64c5ff2
commit 3043633d9c
2 changed files with 42 additions and 28 deletions

View File

@@ -17,7 +17,7 @@ import semmle.python.Concepts
module NoSqlInjection { module NoSqlInjection {
private newtype TFlowState = private newtype TFlowState =
TStringInput() or TStringInput() or
TDictInput() TInterpretedStringInput()
/** A flow state, tracking the structure of the input. */ /** A flow state, tracking the structure of the input. */
abstract class FlowState extends TFlowState { abstract class FlowState extends TFlowState {
@@ -30,29 +30,33 @@ module NoSqlInjection {
override string toString() { result = "StringInput" } override string toString() { result = "StringInput" }
} }
/** A state where input is a dictionary. */ /**
class DictInput extends FlowState, TDictInput { * A state where input is a string that has been interpreted.
override string toString() { result = "DictInput" } * For instance, it could have been turned into a dictionary,
* or evaluated as javascript code.
*/
class InterpretedStringInput extends FlowState, TInterpretedStringInput {
override string toString() { result = "InterpretedStringInput" }
} }
/** A source allowing string inputs. */ /** A source allowing string inputs. */
abstract class StringSource extends DataFlow::Node { } abstract class StringSource extends DataFlow::Node { }
/** A source allowing dictionary inputs. */ /** A source of interpreted strings. */
abstract class DictSource extends DataFlow::Node { } abstract class InterpretedStringSource extends DataFlow::Node { }
/** A sink vulnerable to user controlled strings. */ /** A sink vulnerable to user controlled strings. */
abstract class StringSink extends DataFlow::Node { } abstract class StringSink extends DataFlow::Node { }
/** A sink vulnerable to user controlled dictionaries. */ /** A sink vulnerable to user controlled interpreted strings. */
abstract class DictSink extends DataFlow::Node { } abstract class InterpretedStringSink extends DataFlow::Node { }
/** A data flow node where a string is converted into a dictionary. */ /** A data flow node where a string is being interpreted. */
abstract class StringToDictConversion extends DataFlow::Node { abstract class StringInterpretation extends DataFlow::Node {
/** Gets the argument that specifies the string to be converted. */ /** Gets the argument that specifies the string to be interpreted. */
abstract DataFlow::Node getAnInput(); abstract DataFlow::Node getAnInput();
/** Gets the resulting dictionary. */ /** Gets the result of interpreting the string. */
abstract DataFlow::Node getOutput(); abstract DataFlow::Node getOutput();
} }
@@ -68,14 +72,23 @@ module NoSqlInjection {
} }
} }
/** A NoSQL query that is vulnerable to user controlled dictionaries. */ /** A NoSQL query that is vulnerable to user controlled InterpretedStringionaries. */
class NoSqlExecutionAsDictSink extends DictSink { class NoSqlExecutionAsInterpretedStringSink extends InterpretedStringSink {
NoSqlExecutionAsDictSink() { this = any(NoSqlExecution noSqlExecution).getQuery() } NoSqlExecutionAsInterpretedStringSink() { this = any(NoSqlExecution noSqlExecution).getQuery() }
} }
/** A JSON decoding converts a string to a dictionary. */ /** A JSON decoding converts a string to a Dictionary. */
class JsonDecoding extends Decoding, StringToDictConversion { class JsonDecoding extends Decoding, StringInterpretation {
JsonDecoding() { this.getFormat() in ["JSON", "NoSQL"] } JsonDecoding() { this.getFormat() = "JSON" }
override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() }
override DataFlow::Node getOutput() { result = Decoding.super.getOutput() }
}
/** A NoSQL decoding interprets a string. */
class NoSqlDecoding extends Decoding, StringInterpretation {
NoSqlDecoding() { this.getFormat() = "NoSQL" }
override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() } override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() }

View File

@@ -18,8 +18,8 @@ module NoSqlInjectionConfig implements DataFlow::StateConfigSig {
source instanceof C::StringSource and source instanceof C::StringSource and
state instanceof C::StringInput state instanceof C::StringInput
or or
source instanceof C::DictSource and source instanceof C::InterpretedStringSource and
state instanceof C::DictInput state instanceof C::InterpretedStringInput
} }
predicate isSink(DataFlow::Node sink, FlowState state) { predicate isSink(DataFlow::Node sink, FlowState state) {
@@ -27,29 +27,30 @@ module NoSqlInjectionConfig implements DataFlow::StateConfigSig {
( (
state instanceof C::StringInput state instanceof C::StringInput
or or
// since dictionaries can encode strings // since InterpretedStrings can include strings,
state instanceof C::DictInput // e.g. JSON objects can encode strings.
state instanceof C::InterpretedStringInput
) )
or or
sink instanceof C::DictSink and sink instanceof C::InterpretedStringSink and
state instanceof C::DictInput state instanceof C::InterpretedStringInput
} }
predicate isBarrier(DataFlow::Node node, FlowState state) { predicate isBarrier(DataFlow::Node node, FlowState state) {
// Block `StringInput` paths here, since they change state to `DictInput` // Block `StringInput` paths here, since they change state to `InterpretedStringInput`
exists(C::StringToDictConversion c | node = c.getOutput()) and exists(C::StringInterpretation c | node = c.getOutput()) and
state instanceof C::StringInput state instanceof C::StringInput
} }
predicate isAdditionalFlowStep( predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
) { ) {
exists(C::StringToDictConversion c | exists(C::StringInterpretation c |
nodeFrom = c.getAnInput() and nodeFrom = c.getAnInput() and
nodeTo = c.getOutput() nodeTo = c.getOutput()
) and ) and
stateFrom instanceof C::StringInput and stateFrom instanceof C::StringInput and
stateTo instanceof C::DictInput stateTo instanceof C::InterpretedStringInput
} }
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {