@@ -24,16 +24,38 @@ private predicate isBadResult(DataFlow::Node e) {
24
24
*/
25
25
abstract class Sink extends DataFlow:: Node { }
26
26
27
- /** A taint-tracking sink which models comparisons of sensitive variables. */
28
- private class SensitiveCompareSink extends Sink {
29
- ComparisonExpr c ;
27
+ /** A taint-tracking sink which models comparisons of sensitive expressions using `strings.Compare` function. */
28
+ private class SensitiveStringCompareSink extends Sink {
29
+ SensitiveStringCompareSink ( ) {
30
+ // We select a comparison where a secret or password is tested.
31
+ exists ( DataFlow:: CallNode c , Expr op1 , Expr nonSensitiveOperand |
32
+ c .getTarget ( ) .hasQualifiedName ( "strings" , "Compare" ) and
33
+ c .getArgument ( _) .asExpr ( ) = op1 and
34
+ op1 .( SensitiveVariableAccess ) .getClassification ( ) =
35
+ [ SensitiveExpr:: secret ( ) , SensitiveExpr:: password ( ) ] and
36
+ c .getArgument ( _) .asExpr ( ) = nonSensitiveOperand and
37
+ not op1 = nonSensitiveOperand and
38
+ not (
39
+ // Comparisons with `nil` should be excluded.
40
+ nonSensitiveOperand = Builtin:: nil ( ) .getAReference ( )
41
+ or
42
+ // Comparisons with empty string should also be excluded.
43
+ nonSensitiveOperand .getStringValue ( ) .length ( ) = 0
44
+ )
45
+ |
46
+ // It is important to note that the name of both the operands need not be
47
+ // `sensitive`. Even if one of the operands appears to be sensitive, we consider it a potential sink.
48
+ nonSensitiveOperand = this .asExpr ( )
49
+ )
50
+ }
51
+ }
30
52
53
+ /** A taint-tracking sink which models comparisons of sensitive expressions. */
54
+ private class SensitiveCompareSink extends Sink {
31
55
SensitiveCompareSink ( ) {
32
56
// We select a comparison where a secret or password is tested.
33
- exists ( SensitiveVariableAccess op1 , Expr op2 |
57
+ exists ( SensitiveExpr op1 , Expr op2 , EqualityTestExpr c |
34
58
op1 .getClassification ( ) = [ SensitiveExpr:: secret ( ) , SensitiveExpr:: password ( ) ] and
35
- // exclude grant to avoid FP from OAuth
36
- not op1 .getClassification ( ) .matches ( "%grant%" ) and
37
59
op1 = c .getAnOperand ( ) and
38
60
op2 = c .getAnOperand ( ) and
39
61
not op1 = op2 and
@@ -45,13 +67,34 @@ private class SensitiveCompareSink extends Sink {
45
67
op2 .getStringValue ( ) .length ( ) = 0
46
68
)
47
69
|
48
- // It is important to note that the name of both the operands need not be
49
- // `sensitive`. Even if one of the operands appears to be sensitive, we consider it a potential sink.
50
- c .getAnOperand ( ) = this .asExpr ( )
70
+ op2 = this .asExpr ( )
51
71
)
52
72
}
73
+ }
53
74
54
- DataFlow:: Node getOtherOperand ( ) { result .asExpr ( ) = c .getAnOperand ( ) and not result = this }
75
+ /** A taint-tracking sink which models comparisons of sensitive strings. */
76
+ private class SensitiveStringSink extends Sink {
77
+ SensitiveStringSink ( ) {
78
+ // We select a comparison where a secret or password is tested.
79
+ exists ( StringLit op1 , Expr op2 , EqualityTestExpr c |
80
+ op1 .getStringValue ( )
81
+ .regexpMatch ( HeuristicNames:: maybeSensitive ( [
82
+ SensitiveExpr:: secret ( ) , SensitiveExpr:: password ( )
83
+ ] ) ) and
84
+ op1 = c .getAnOperand ( ) and
85
+ op2 = c .getAnOperand ( ) and
86
+ not op1 = op2 and
87
+ not (
88
+ // Comparisons with `nil` should be excluded.
89
+ op2 = Builtin:: nil ( ) .getAReference ( )
90
+ or
91
+ // Comparisons with empty string should also be excluded.
92
+ op2 .getStringValue ( ) .length ( ) = 0
93
+ )
94
+ |
95
+ op2 = this .asExpr ( )
96
+ )
97
+ }
55
98
}
56
99
57
100
class SecretTracking extends TaintTracking:: Configuration {
@@ -65,8 +108,6 @@ class SecretTracking extends TaintTracking::Configuration {
65
108
}
66
109
67
110
from SecretTracking cfg , DataFlow:: PathNode source , DataFlow:: PathNode sink
68
- where
69
- cfg .hasFlowPath ( source , sink ) and
70
- not cfg .hasFlowTo ( sink .getNode ( ) .( SensitiveCompareSink ) .getOtherOperand ( ) )
111
+ where cfg .hasFlowPath ( source , sink )
71
112
select sink .getNode ( ) , source , sink , "$@ may be vulnerable to timing attacks." , source .getNode ( ) ,
72
113
"Hardcoded String"
0 commit comments