@@ -8,7 +8,6 @@ private import semmle.python.dataflow.new.DataFlow
8
8
// Need to import since frameworks can extend `RemoteFlowSource::Range`
9
9
private import semmle.python.Frameworks
10
10
private import semmle.python.Concepts
11
- private import semmle.python.security.SensitiveData as OldSensitiveData
12
11
private import semmle.python.security.internal.SensitiveDataHeuristics as SensitiveDataHeuristics
13
12
14
13
// We export these explicitly, so we don't also export the `HeuristicNames` module.
@@ -49,17 +48,94 @@ module SensitiveDataSource {
49
48
}
50
49
}
51
50
52
- // TODO: rewrite this to not rely on the old points-to implementation
53
- private class PortOfOldModeling extends SensitiveDataSource :: Range {
54
- OldSensitiveData :: SensitiveData :: Source oldSensitiveSource ;
51
+ /** Actual sensitive data modeling */
52
+ private module SensitiveDataModeling {
53
+ private import SensitiveDataHeuristics :: HeuristicNames
55
54
56
- PortOfOldModeling ( ) { this .asCfgNode ( ) = oldSensitiveSource }
55
+ /**
56
+ * Gets a reference to a function that is considered to be a sensitive source of
57
+ * `classification`.
58
+ */
59
+ private DataFlow:: LocalSourceNode sensitiveFunction (
60
+ DataFlow:: TypeTracker t , SensitiveDataClassification classification
61
+ ) {
62
+ t .start ( ) and
63
+ exists ( Function f |
64
+ nameIndicatesSensitiveData ( f .getName ( ) , classification ) and
65
+ result .asExpr ( ) = f .getDefinition ( )
66
+ )
67
+ or
68
+ exists ( DataFlow:: TypeTracker t2 | result = sensitiveFunction ( t2 , classification ) .track ( t2 , t ) )
69
+ }
57
70
58
- override SensitiveDataClassification getClassification ( ) {
59
- exists ( OldSensitiveData:: SensitiveData classification |
60
- oldSensitiveSource .isSourceOf ( classification )
61
- |
62
- classification = "sensitive.data." + result
71
+ /**
72
+ * Gets a reference to a function that is considered to be a sensitive source of
73
+ * `classification`.
74
+ */
75
+ DataFlow:: Node sensitiveFunction ( SensitiveDataClassification classification ) {
76
+ sensitiveFunction ( DataFlow:: TypeTracker:: end ( ) , classification ) .flowsTo ( result )
77
+ }
78
+
79
+ /**
80
+ * Gets a reference to a string constant that, if used as the key in a lookup,
81
+ * indicates the presence of sensitive data with `classification`.
82
+ */
83
+ private DataFlow:: LocalSourceNode sensitiveLookupStringConst (
84
+ DataFlow:: TypeTracker t , SensitiveDataClassification classification
85
+ ) {
86
+ t .start ( ) and
87
+ nameIndicatesSensitiveData ( result .asExpr ( ) .( StrConst ) .getText ( ) , classification )
88
+ or
89
+ exists ( DataFlow:: TypeTracker t2 |
90
+ result = sensitiveLookupStringConst ( t2 , classification ) .track ( t2 , t )
63
91
)
64
92
}
93
+
94
+ /**
95
+ * Gets a reference to a string constant that, if used as the key in a lookup,
96
+ * indicates the presence of sensitive data with `classification`.
97
+ */
98
+ DataFlow:: Node sensitiveLookupStringConst ( SensitiveDataClassification classification ) {
99
+ sensitiveLookupStringConst ( DataFlow:: TypeTracker:: end ( ) , classification ) .flowsTo ( result )
100
+ }
101
+
102
+ /** A function call that is considered a source of sensitive data. */
103
+ class SensitiveFunctionCall extends SensitiveDataSource:: Range , DataFlow:: CallCfgNode {
104
+ SensitiveDataClassification classification ;
105
+
106
+ SensitiveFunctionCall ( ) {
107
+ this .getFunction ( ) = sensitiveFunction ( classification )
108
+ or
109
+ nameIndicatesSensitiveData ( this .getFunction ( ) .asCfgNode ( ) .( NameNode ) .getId ( ) , classification )
110
+ }
111
+
112
+ override SensitiveDataClassification getClassification ( ) { result = classification }
113
+ }
114
+
115
+ /** An attribute access that is considered a source of sensitive data. */
116
+ class SensitiveAttributeAccess extends SensitiveDataSource:: Range {
117
+ SensitiveDataClassification classification ;
118
+
119
+ SensitiveAttributeAccess ( ) {
120
+ nameIndicatesSensitiveData ( this .( DataFlow:: AttrRead ) .getAttributeName ( ) , classification )
121
+ or
122
+ // I considered excluding any `from ... import something_sensitive`, but then realized that
123
+ // we should flag up `form ... import password as ...` as a password
124
+ this .( DataFlow:: AttrRead ) .getAttributeNameExpr ( ) = sensitiveLookupStringConst ( classification )
125
+ }
126
+
127
+ override SensitiveDataClassification getClassification ( ) { result = classification }
128
+ }
129
+
130
+ /** A call to `get` on an object, where the key indicates the result will be sensitive data. */
131
+ class SensitiveGetCall extends SensitiveDataSource:: Range , DataFlow:: CallCfgNode {
132
+ SensitiveDataClassification classification ;
133
+
134
+ SensitiveGetCall ( ) {
135
+ this .getFunction ( ) .asCfgNode ( ) .( AttrNode ) .getName ( ) = "get" and
136
+ this .getArg ( 0 ) = sensitiveLookupStringConst ( classification )
137
+ }
138
+
139
+ override SensitiveDataClassification getClassification ( ) { result = classification }
140
+ }
65
141
}
0 commit comments