@@ -46,7 +46,7 @@ module HardcodedKeys {
46
46
/**
47
47
* A hardcoded string literal as a source for JWT token signing vulnerabilities.
48
48
*/
49
- class HardcodedStringSource extends Source {
49
+ private class HardcodedStringSource extends Source {
50
50
HardcodedStringSource ( ) {
51
51
this .asExpr ( ) instanceof StringLit and
52
52
not ( isTestCode ( this .asExpr ( ) ) or isDemoCode ( this .asExpr ( ) ) )
@@ -166,7 +166,7 @@ module HardcodedKeys {
166
166
}
167
167
168
168
/** Mark an empty string returned with an error as a sanitizer */
169
- class EmptyErrorSanitizer extends Sanitizer {
169
+ private class EmptyErrorSanitizer extends Sanitizer {
170
170
EmptyErrorSanitizer ( ) {
171
171
exists ( ReturnStmt r , DataFlow:: CallNode c |
172
172
c .getTarget ( ) .hasQualifiedName ( "errors" , "New" ) and
@@ -178,7 +178,7 @@ module HardcodedKeys {
178
178
}
179
179
180
180
/** Mark any formatting string call as a sanitizer */
181
- class FormattingSanitizer extends Sanitizer {
181
+ private class FormattingSanitizer extends Sanitizer {
182
182
FormattingSanitizer ( ) { exists ( Formatting:: StringFormatCall s | s .getAResult ( ) = this ) }
183
183
}
184
184
@@ -188,19 +188,6 @@ module HardcodedKeys {
188
188
*/
189
189
private class RandSliceSanitizer extends Sanitizer {
190
190
RandSliceSanitizer ( ) {
191
- exists ( DataFlow:: CallNode randint , string name , DataFlow:: ElementReadNode r |
192
- (
193
- randint .getTarget ( ) .hasQualifiedName ( "math/rand" , name ) or
194
- randint .getTarget ( ) .( Method ) .hasQualifiedName ( "math/rand" , "Rand" , name )
195
- ) and
196
- name =
197
- [
198
- "ExpFloat64" , "Float32" , "Float64" , "Int" , "Int31" , "Int31n" , "Int63" , "Int63n" , "Intn" ,
199
- "NormFloat64" , "Uint32" , "Uint64"
200
- ] and
201
- r .reads ( this , randint .getAResult ( ) .getASuccessor * ( ) )
202
- )
203
- or
204
191
// Sanitize flows like this:
205
192
// func GenerateCryptoString(n int) (string, error) {
206
193
// const chars = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
@@ -215,12 +202,20 @@ module HardcodedKeys {
215
202
// return string(ret), nil
216
203
// }
217
204
exists (
218
- DataFlow:: CallNode randint , DataFlow:: MethodCallNode bigint , DataFlow:: ElementReadNode r
205
+ DataFlow:: CallNode randint , string name , DataFlow:: ElementReadNode r , DataFlow:: Node index
219
206
|
220
- randint .getTarget ( ) .hasQualifiedName ( "crypto/rand" , "Int" ) and
221
- bigint .getTarget ( ) .hasQualifiedName ( "math/big" , "Int" , "Int64" ) and
222
- bigint .getReceiver ( ) = randint .getResult ( 0 ) .getASuccessor * ( ) and
223
- r .reads ( this , bigint .getAResult ( ) .getASuccessor * ( ) )
207
+ (
208
+ randint .getTarget ( ) .hasQualifiedName ( "math/rand" , name ) or
209
+ randint .getTarget ( ) .( Method ) .hasQualifiedName ( "math/rand" , "Rand" , name ) or
210
+ randint .getTarget ( ) .hasQualifiedName ( "crypto/rand" , "Int" )
211
+ ) and
212
+ name =
213
+ [
214
+ "ExpFloat64" , "Float32" , "Float64" , "Int" , "Int31" , "Int31n" , "Int63" , "Int63n" , "Intn" ,
215
+ "NormFloat64" , "Uint32" , "Uint64"
216
+ ] and
217
+ TaintTracking:: localTaint ( randint .getAResult ( ) , index ) and
218
+ r .reads ( this , index )
224
219
)
225
220
or
226
221
// Sanitize flows like :
@@ -232,29 +227,49 @@ module HardcodedKeys {
232
227
// }
233
228
// return string(bytes)
234
229
// }
235
- exists ( DataFlow:: CallNode randread , DataFlow:: Node rand , DataFlow :: ElementReadNode r |
230
+ exists ( DataFlow:: CallNode randread , DataFlow:: Node rand |
236
231
randread .getTarget ( ) .hasQualifiedName ( "crypto/rand" , "Read" ) and
237
232
TaintTracking:: localTaint ( any ( DataFlow:: PostUpdateNode pun |
238
233
pun .getPreUpdateNode ( ) = randread .getArgument ( 0 )
239
234
) , rand ) and
240
- (
241
- // Flow through a ModExpr if any of the operands are tainted.
242
- // For ex, in the case shown above,
243
- // `bytes[i] = characters[x%byte(len(characters))]`
244
- // given x is cryptographically secure random number,
245
- // we can assume that `bytes` is random and cryptographically secure.
246
- exists ( ModExpr e | e .getAnOperand ( ) = rand .asExpr ( ) |
247
- r .reads ( this , e .getGlobalValueNumber ( ) .getANode ( ) )
248
- )
249
- or
250
- // This is an alternative case where the code uses `x` directly instead
251
- // `bytes[i] = characters[x]`
252
- r .reads ( this .getAPredecessor * ( ) , rand )
253
- )
235
+ this .( DataFlow:: ElementReadNode ) .reads ( _, rand )
254
236
)
255
237
}
256
238
}
257
239
240
+ /**
241
+ * Models flow from a call to `Int64` if the receiver is tainted
242
+ */
243
+ private class BigIntFlow extends TaintTracking:: FunctionModel {
244
+ BigIntFlow ( ) { this .( Method ) .hasQualifiedName ( "math/big" , "Int" , "Int64" ) }
245
+
246
+ override predicate hasTaintFlow ( DataFlow:: FunctionInput inp , DataFlow:: FunctionOutput outp ) {
247
+ inp .isReceiver ( ) and
248
+ outp .isResult ( 0 )
249
+ }
250
+ }
251
+
252
+ /*
253
+ * This is code is used to model taint flow through a binary operation such as a
254
+ * modulo `%` operation or an addition `+` operation
255
+ */
256
+
257
+ private class BinExpAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
258
+ // This is required to model the sanitizers for the `HardcodedKeys` query.
259
+ // This is required to correctly detect a sanitizer such as the one shown below.
260
+ // func GenerateRandomString(size int) string {
261
+ // var bytes = make([]byte, size)
262
+ // rand.Read(bytes)
263
+ // for i, x := range bytes {
264
+ // bytes[i] = characters[x%byte(len(characters))]
265
+ // }
266
+ // return string(bytes)
267
+ // }
268
+ override predicate step ( DataFlow:: Node prev , DataFlow:: Node succ ) {
269
+ exists ( BinaryExpr b | b .getAnOperand ( ) = prev .asExpr ( ) | succ .asExpr ( ) = b )
270
+ }
271
+ }
272
+
258
273
/**
259
274
* A configuration depicting taint flow for studying JWT token signing vulnerabilities.
260
275
*/
@@ -267,6 +282,8 @@ module HardcodedKeys {
267
282
268
283
override predicate isSanitizer ( DataFlow:: Node sanitizer ) { sanitizer instanceof Sanitizer }
269
284
285
+ // override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
286
+ // }
270
287
override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
271
288
guard instanceof SanitizerGuard
272
289
}
0 commit comments