@@ -3,53 +3,37 @@ import semmle.python.dataflow.new.DataFlow
3
3
import semmle.python.dataflow.new.DataFlow2
4
4
import semmle.python.dataflow.new.TaintTracking
5
5
import semmle.python.dataflow.new.TaintTracking2
6
- import experimental.semmle.python.Concepts
7
6
import semmle.python.dataflow.new.RemoteFlowSources
8
- import semmle.python.ApiGraphs
9
7
import semmle.python.security.dataflow.ChainedConfigs12
8
+ import experimental.semmle.python.Concepts
9
+ import semmle.python.Concepts
10
10
11
- class JsonLoadsCall extends DataFlow:: CallCfgNode {
12
- JsonLoadsCall ( ) { this = API:: moduleImport ( "json" ) .getMember ( "loads" ) .getACall ( ) }
13
-
14
- DataFlow:: Node getLoadNode ( ) { result = this .getArg ( 0 ) }
15
- }
16
-
17
- class XmlToDictParseCall extends DataFlow:: CallCfgNode {
18
- XmlToDictParseCall ( ) { this = API:: moduleImport ( "xmltodict" ) .getMember ( "parse" ) .getACall ( ) }
19
-
20
- DataFlow:: Node getParseNode ( ) { result = this .getArg ( 0 ) }
21
- }
22
-
23
- class UltraJsonLoadsCall extends DataFlow:: CallCfgNode {
24
- UltraJsonLoadsCall ( ) { this = API:: moduleImport ( "ujson" ) .getMember ( "loads" ) .getACall ( ) }
25
-
26
- DataFlow:: Node getLoadNode ( ) { result = this .getArg ( 0 ) }
27
- }
28
-
29
- class DataToDictSink extends DataFlow:: Node {
30
- DataToDictSink ( ) {
31
- this = any ( JsonLoadsCall jsonLoads ) .getLoadNode ( ) or
32
- this = any ( XmlToDictParseCall jsonLoads ) .getParseNode ( ) or
33
- this = any ( UltraJsonLoadsCall jsonLoads ) .getLoadNode ( )
34
- }
35
- }
36
-
11
+ /**
12
+ * A taint-tracking configuration for detecting string-to-dict conversions.
13
+ */
37
14
class RFSToDictConfig extends TaintTracking:: Configuration {
38
15
RFSToDictConfig ( ) { this = "RFSToDictConfig" }
39
16
40
17
override predicate isSource ( DataFlow:: Node source ) { source instanceof RemoteFlowSource }
41
18
42
- override predicate isSink ( DataFlow:: Node sink ) { sink instanceof DataToDictSink }
19
+ override predicate isSink ( DataFlow:: Node sink ) {
20
+ exists ( Decoding decoding | decoding .getFormat ( ) = "JSON" and sink = decoding )
21
+ }
43
22
44
23
override predicate isSanitizer ( DataFlow:: Node sanitizer ) {
45
24
sanitizer = any ( NoSQLSanitizer noSQLSanitizer ) .getAnInput ( )
46
25
}
47
26
}
48
27
28
+ /**
29
+ * A taint-tracking configuration for detecting NoSQL injections (previously converted to a dict).
30
+ */
49
31
class FromDataDictToSink extends TaintTracking2:: Configuration {
50
32
FromDataDictToSink ( ) { this = "FromDataDictToSink" }
51
33
52
- override predicate isSource ( DataFlow:: Node source ) { source instanceof DataToDictSink }
34
+ override predicate isSource ( DataFlow:: Node source ) {
35
+ exists ( Decoding decoding | decoding .getFormat ( ) = "JSON" and source = decoding )
36
+ }
53
37
54
38
override predicate isSink ( DataFlow:: Node sink ) { sink = any ( NoSQLQuery noSQLQuery ) .getQuery ( ) }
55
39
@@ -58,6 +42,9 @@ class FromDataDictToSink extends TaintTracking2::Configuration {
58
42
}
59
43
}
60
44
45
+ /**
46
+ * A predicate checking string-to-dict conversion and its arrival to a NoSQL injection sink.
47
+ */
61
48
predicate noSQLInjectionFlow ( CustomPathNode source , CustomPathNode sink ) {
62
49
exists (
63
50
RFSToDictConfig config , DataFlow:: PathNode mid1 , DataFlow2:: PathNode mid2 ,
0 commit comments