@@ -229,43 +229,43 @@ module TaintTracking {
229
229
* promises.
230
230
*/
231
231
private class HeapTaintStep extends AdditionalTaintStep {
232
- HeapTaintStep ( ) {
233
- this = DataFlow:: valueNode ( _) or
234
- this = DataFlow:: parameterNode ( _) or
235
- this instanceof DataFlow:: PropRead
236
- }
232
+ HeapTaintStep ( ) { heapStep ( _, this ) }
237
233
238
234
override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
239
- succ = this and
240
- exists ( Expr e , Expr f | e = this .asExpr ( ) and f = pred .asExpr ( ) |
241
- // arrays with tainted elements and objects with tainted property names are tainted
242
- e .( ArrayExpr ) .getAnElement ( ) = f
243
- or
244
- exists ( Property prop | e .( ObjectExpr ) .getAProperty ( ) = prop |
245
- prop .isComputed ( ) and f = prop .getNameExpr ( )
246
- )
247
- or
248
- // awaiting a tainted expression gives a tainted result
249
- e .( AwaitExpr ) .getOperand ( ) = f
250
- or
251
- // spreading a tainted object into an object literal gives a tainted object
252
- e .( ObjectExpr ) .getAProperty ( ) .( SpreadProperty ) .getInit ( ) .( SpreadElement ) .getOperand ( ) = f
253
- or
254
- // spreading a tainted value into an array literal gives a tainted array
255
- e .( ArrayExpr ) .getAnElement ( ) .( SpreadElement ) .getOperand ( ) = f
235
+ heapStep ( pred , succ ) and succ = this
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Holds if there is taint propagation through the heap from `pred` to `succ`.
241
+ */
242
+ private predicate heapStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
243
+ exists ( Expr e , Expr f | e = succ .asExpr ( ) and f = pred .asExpr ( ) |
244
+ // arrays with tainted elements and objects with tainted property names are tainted
245
+ e .( ArrayExpr ) .getAnElement ( ) = f
246
+ or
247
+ exists ( Property prop | e .( ObjectExpr ) .getAProperty ( ) = prop |
248
+ prop .isComputed ( ) and f = prop .getNameExpr ( )
256
249
)
257
250
or
258
- // reading from a tainted object yields a tainted result
259
- this = succ and
260
- succ .( DataFlow:: PropRead ) .getBase ( ) = pred
251
+ // awaiting a tainted expression gives a tainted result
252
+ e .( AwaitExpr ) .getOperand ( ) = f
261
253
or
262
- // iterating over a tainted iterator taints the loop variable
263
- exists ( ForOfStmt fos |
264
- this = DataFlow:: valueNode ( fos .getIterationDomain ( ) ) and
265
- pred = this and
266
- succ = DataFlow:: lvalueNode ( fos .getLValue ( ) )
267
- )
268
- }
254
+ // spreading a tainted object into an object literal gives a tainted object
255
+ e .( ObjectExpr ) .getAProperty ( ) .( SpreadProperty ) .getInit ( ) .( SpreadElement ) .getOperand ( ) = f
256
+ or
257
+ // spreading a tainted value into an array literal gives a tainted array
258
+ e .( ArrayExpr ) .getAnElement ( ) .( SpreadElement ) .getOperand ( ) = f
259
+ )
260
+ or
261
+ // reading from a tainted object yields a tainted result
262
+ succ .( DataFlow:: PropRead ) .getBase ( ) = pred
263
+ or
264
+ // iterating over a tainted iterator taints the loop variable
265
+ exists ( ForOfStmt fos |
266
+ pred = DataFlow:: valueNode ( fos .getIterationDomain ( ) ) and
267
+ succ = DataFlow:: lvalueNode ( fos .getLValue ( ) )
268
+ )
269
269
}
270
270
271
271
/**
@@ -388,84 +388,91 @@ module TaintTracking {
388
388
* functions defined in the standard library.
389
389
*/
390
390
private class StringManipulationTaintStep extends AdditionalTaintStep , DataFlow:: ValueNode {
391
+ StringManipulationTaintStep ( ) { stringManipulationStep ( _, this ) }
392
+
391
393
override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
392
394
succ = this and
395
+ stringManipulationStep ( pred , succ )
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Holds if taint can propagate from `pred` to `succ` with a step related to string manipulation.
401
+ */
402
+ private predicate stringManipulationStep ( DataFlow:: Node pred , DataFlow:: ValueNode succ ) {
403
+ // string operations that propagate taint
404
+ exists ( string name | name = succ .getAstNode ( ) .( MethodCallExpr ) .getMethodName ( ) |
405
+ pred .asExpr ( ) = succ .getAstNode ( ) .( MethodCallExpr ) .getReceiver ( ) and
393
406
(
394
- // string operations that propagate taint
395
- exists ( string name | name = astNode .( MethodCallExpr ) .getMethodName ( ) |
396
- pred .asExpr ( ) = astNode .( MethodCallExpr ) .getReceiver ( ) and
397
- (
398
- // sorted, interesting, properties of String.prototype
399
- name = "anchor" or
400
- name = "big" or
401
- name = "blink" or
402
- name = "bold" or
403
- name = "concat" or
404
- name = "fixed" or
405
- name = "fontcolor" or
406
- name = "fontsize" or
407
- name = "italics" or
408
- name = "link" or
409
- name = "padEnd" or
410
- name = "padStart" or
411
- name = "repeat" or
412
- name = "replace" or
413
- name = "slice" or
414
- name = "small" or
415
- name = "split" or
416
- name = "strike" or
417
- name = "sub" or
418
- name = "substr" or
419
- name = "substring" or
420
- name = "sup" or
421
- name = "toLocaleLowerCase" or
422
- name = "toLocaleUpperCase" or
423
- name = "toLowerCase" or
424
- name = "toUpperCase" or
425
- name = "trim" or
426
- name = "trimLeft" or
427
- name = "trimRight" or
428
- // sorted, interesting, properties of Object.prototype
429
- name = "toString" or
430
- name = "valueOf" or
431
- // sorted, interesting, properties of Array.prototype
432
- name = "join"
433
- )
434
- or
435
- exists ( int i | pred .asExpr ( ) = astNode .( MethodCallExpr ) .getArgument ( i ) |
436
- name = "concat"
437
- or
438
- name = "replace" and i = 1
439
- )
440
- )
441
- or
442
- // standard library constructors that propagate taint: `RegExp` and `String`
443
- exists ( DataFlow:: InvokeNode invk , string gv | gv = "RegExp" or gv = "String" |
444
- this = invk and
445
- invk = DataFlow:: globalVarRef ( gv ) .getAnInvocation ( ) and
446
- pred = invk .getArgument ( 0 )
447
- )
448
- or
449
- // String.fromCharCode and String.fromCodePoint
450
- exists ( int i , MethodCallExpr mce |
451
- mce = astNode and
452
- pred .asExpr ( ) = mce .getArgument ( i ) and
453
- ( mce .getMethodName ( ) = "fromCharCode" or mce .getMethodName ( ) = "fromCodePoint" )
454
- )
407
+ // sorted, interesting, properties of String.prototype
408
+ name = "anchor" or
409
+ name = "big" or
410
+ name = "blink" or
411
+ name = "bold" or
412
+ name = "concat" or
413
+ name = "fixed" or
414
+ name = "fontcolor" or
415
+ name = "fontsize" or
416
+ name = "italics" or
417
+ name = "link" or
418
+ name = "padEnd" or
419
+ name = "padStart" or
420
+ name = "repeat" or
421
+ name = "replace" or
422
+ name = "slice" or
423
+ name = "small" or
424
+ name = "split" or
425
+ name = "strike" or
426
+ name = "sub" or
427
+ name = "substr" or
428
+ name = "substring" or
429
+ name = "sup" or
430
+ name = "toLocaleLowerCase" or
431
+ name = "toLocaleUpperCase" or
432
+ name = "toLowerCase" or
433
+ name = "toUpperCase" or
434
+ name = "trim" or
435
+ name = "trimLeft" or
436
+ name = "trimRight" or
437
+ // sorted, interesting, properties of Object.prototype
438
+ name = "toString" or
439
+ name = "valueOf" or
440
+ // sorted, interesting, properties of Array.prototype
441
+ name = "join"
442
+ )
443
+ or
444
+ exists ( int i | pred .asExpr ( ) = succ .getAstNode ( ) .( MethodCallExpr ) .getArgument ( i ) |
445
+ name = "concat"
455
446
or
456
- // `(encode|decode)URI(Component)?` propagate taint
457
- exists ( DataFlow:: CallNode c , string name |
458
- this = c and
459
- c = DataFlow:: globalVarRef ( name ) .getACall ( ) and
460
- pred = c .getArgument ( 0 )
461
- |
462
- name = "encodeURI" or
463
- name = "decodeURI" or
464
- name = "encodeURIComponent" or
465
- name = "decodeURIComponent"
466
- )
447
+ name = "replace" and i = 1
467
448
)
468
- }
449
+ )
450
+ or
451
+ // standard library constructors that propagate taint: `RegExp` and `String`
452
+ exists ( DataFlow:: InvokeNode invk , string gv | gv = "RegExp" or gv = "String" |
453
+ succ = invk and
454
+ invk = DataFlow:: globalVarRef ( gv ) .getAnInvocation ( ) and
455
+ pred = invk .getArgument ( 0 )
456
+ )
457
+ or
458
+ // String.fromCharCode and String.fromCodePoint
459
+ exists ( int i , MethodCallExpr mce |
460
+ mce = succ .getAstNode ( ) and
461
+ pred .asExpr ( ) = mce .getArgument ( i ) and
462
+ ( mce .getMethodName ( ) = "fromCharCode" or mce .getMethodName ( ) = "fromCodePoint" )
463
+ )
464
+ or
465
+ // `(encode|decode)URI(Component)?` propagate taint
466
+ exists ( DataFlow:: CallNode c , string name |
467
+ succ = c and
468
+ c = DataFlow:: globalVarRef ( name ) .getACall ( ) and
469
+ pred = c .getArgument ( 0 )
470
+ |
471
+ name = "encodeURI" or
472
+ name = "decodeURI" or
473
+ name = "encodeURIComponent" or
474
+ name = "decodeURIComponent"
475
+ )
469
476
}
470
477
471
478
/**
0 commit comments