Skip to content

Commit 3043633

Browse files
committed
Python: Some renaming of flow states
1 parent d5b64c5 commit 3043633

File tree

2 files changed

+42
-28
lines changed

2 files changed

+42
-28
lines changed

python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionCustomizations.qll

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import semmle.python.Concepts
1717
module NoSqlInjection {
1818
private newtype TFlowState =
1919
TStringInput() or
20-
TDictInput()
20+
TInterpretedStringInput()
2121

2222
/** A flow state, tracking the structure of the input. */
2323
abstract class FlowState extends TFlowState {
@@ -30,29 +30,33 @@ module NoSqlInjection {
3030
override string toString() { result = "StringInput" }
3131
}
3232

33-
/** A state where input is a dictionary. */
34-
class DictInput extends FlowState, TDictInput {
35-
override string toString() { result = "DictInput" }
33+
/**
34+
* A state where input is a string that has been interpreted.
35+
* For instance, it could have been turned into a dictionary,
36+
* or evaluated as javascript code.
37+
*/
38+
class InterpretedStringInput extends FlowState, TInterpretedStringInput {
39+
override string toString() { result = "InterpretedStringInput" }
3640
}
3741

3842
/** A source allowing string inputs. */
3943
abstract class StringSource extends DataFlow::Node { }
4044

41-
/** A source allowing dictionary inputs. */
42-
abstract class DictSource extends DataFlow::Node { }
45+
/** A source of interpreted strings. */
46+
abstract class InterpretedStringSource extends DataFlow::Node { }
4347

4448
/** A sink vulnerable to user controlled strings. */
4549
abstract class StringSink extends DataFlow::Node { }
4650

47-
/** A sink vulnerable to user controlled dictionaries. */
48-
abstract class DictSink extends DataFlow::Node { }
51+
/** A sink vulnerable to user controlled interpreted strings. */
52+
abstract class InterpretedStringSink extends DataFlow::Node { }
4953

50-
/** A data flow node where a string is converted into a dictionary. */
51-
abstract class StringToDictConversion extends DataFlow::Node {
52-
/** Gets the argument that specifies the string to be converted. */
54+
/** A data flow node where a string is being interpreted. */
55+
abstract class StringInterpretation extends DataFlow::Node {
56+
/** Gets the argument that specifies the string to be interpreted. */
5357
abstract DataFlow::Node getAnInput();
5458

55-
/** Gets the resulting dictionary. */
59+
/** Gets the result of interpreting the string. */
5660
abstract DataFlow::Node getOutput();
5761
}
5862

@@ -68,14 +72,23 @@ module NoSqlInjection {
6872
}
6973
}
7074

71-
/** A NoSQL query that is vulnerable to user controlled dictionaries. */
72-
class NoSqlExecutionAsDictSink extends DictSink {
73-
NoSqlExecutionAsDictSink() { this = any(NoSqlExecution noSqlExecution).getQuery() }
75+
/** A NoSQL query that is vulnerable to user controlled InterpretedStringionaries. */
76+
class NoSqlExecutionAsInterpretedStringSink extends InterpretedStringSink {
77+
NoSqlExecutionAsInterpretedStringSink() { this = any(NoSqlExecution noSqlExecution).getQuery() }
7478
}
7579

76-
/** A JSON decoding converts a string to a dictionary. */
77-
class JsonDecoding extends Decoding, StringToDictConversion {
78-
JsonDecoding() { this.getFormat() in ["JSON", "NoSQL"] }
80+
/** A JSON decoding converts a string to a Dictionary. */
81+
class JsonDecoding extends Decoding, StringInterpretation {
82+
JsonDecoding() { this.getFormat() = "JSON" }
83+
84+
override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() }
85+
86+
override DataFlow::Node getOutput() { result = Decoding.super.getOutput() }
87+
}
88+
89+
/** A NoSQL decoding interprets a string. */
90+
class NoSqlDecoding extends Decoding, StringInterpretation {
91+
NoSqlDecoding() { this.getFormat() = "NoSQL" }
7992

8093
override DataFlow::Node getAnInput() { result = Decoding.super.getAnInput() }
8194

python/ql/lib/semmle/python/security/dataflow/NoSQLInjectionQuery.qll

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,39 @@ module NoSqlInjectionConfig implements DataFlow::StateConfigSig {
1818
source instanceof C::StringSource and
1919
state instanceof C::StringInput
2020
or
21-
source instanceof C::DictSource and
22-
state instanceof C::DictInput
21+
source instanceof C::InterpretedStringSource and
22+
state instanceof C::InterpretedStringInput
2323
}
2424

2525
predicate isSink(DataFlow::Node sink, FlowState state) {
2626
sink instanceof C::StringSink and
2727
(
2828
state instanceof C::StringInput
2929
or
30-
// since dictionaries can encode strings
31-
state instanceof C::DictInput
30+
// since InterpretedStrings can include strings,
31+
// e.g. JSON objects can encode strings.
32+
state instanceof C::InterpretedStringInput
3233
)
3334
or
34-
sink instanceof C::DictSink and
35-
state instanceof C::DictInput
35+
sink instanceof C::InterpretedStringSink and
36+
state instanceof C::InterpretedStringInput
3637
}
3738

3839
predicate isBarrier(DataFlow::Node node, FlowState state) {
39-
// Block `StringInput` paths here, since they change state to `DictInput`
40-
exists(C::StringToDictConversion c | node = c.getOutput()) and
40+
// Block `StringInput` paths here, since they change state to `InterpretedStringInput`
41+
exists(C::StringInterpretation c | node = c.getOutput()) and
4142
state instanceof C::StringInput
4243
}
4344

4445
predicate isAdditionalFlowStep(
4546
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
4647
) {
47-
exists(C::StringToDictConversion c |
48+
exists(C::StringInterpretation c |
4849
nodeFrom = c.getAnInput() and
4950
nodeTo = c.getOutput()
5051
) and
5152
stateFrom instanceof C::StringInput and
52-
stateTo instanceof C::DictInput
53+
stateTo instanceof C::InterpretedStringInput
5354
}
5455

5556
predicate isBarrier(DataFlow::Node node) {

0 commit comments

Comments
 (0)