@@ -55,29 +55,17 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
55
55
56
56
override predicate isSink ( DataFlow:: Node sink ) {
57
57
exists (
58
- MethodAccess mua , MethodAccess mda // invoke `md.digest()` with only one call of `md. update(password)`, that is, without the call of `md.update(digest)`
58
+ MethodAccess mua // invoke `md.update(password)` without the call of `md.update(digest)`
59
59
|
60
60
sink .asExpr ( ) = mua .getArgument ( 0 ) and
61
- mua .getMethod ( ) instanceof MDUpdateMethod and // md.update(password)
62
- mda .getMethod ( ) instanceof MDDigestMethod and
63
- mda .getNumArgument ( ) = 0 and // md.digest()
64
- mda .getQualifier ( ) = mua .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) and
65
- not exists ( MethodAccess mua2 |
66
- mua2 .getMethod ( ) instanceof MDUpdateMethod and // md.update(salt)
67
- mua2 .getQualifier ( ) = mua .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) and
68
- mua2 != mua
69
- )
61
+ mua .getMethod ( ) instanceof MDUpdateMethod // md.update(password)
70
62
)
71
63
or
72
64
// invoke `md.digest(password)` without another call of `md.update(salt)`
73
65
exists ( MethodAccess mda |
74
66
sink .asExpr ( ) = mda .getArgument ( 0 ) and
75
67
mda .getMethod ( ) instanceof MDDigestMethod and // md.digest(password)
76
- mda .getNumArgument ( ) = 1 and
77
- not exists ( MethodAccess mua |
78
- mua .getMethod ( ) instanceof MDUpdateMethod and // md.update(salt)
79
- mua .getQualifier ( ) = mda .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( )
80
- )
68
+ mda .getNumArgument ( ) = 1
81
69
)
82
70
}
83
71
@@ -96,9 +84,37 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
96
84
) // System.arraycopy(password.getBytes(), ...)
97
85
or
98
86
exists ( AddExpr e | node .asExpr ( ) = e .getAnOperand ( ) ) // password+salt
87
+ or
88
+ exists ( MethodAccess mua , MethodAccess ma |
89
+ ma .getArgument ( 0 ) = node .asExpr ( ) and // Detect wrapper methods that invoke `md.update(salt)`
90
+ ma != mua and
91
+ (
92
+ mua .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) = ma .getQualifier ( )
93
+ or
94
+ mua .getAnArgument ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) = ma .getQualifier ( )
95
+ or
96
+ mua .getQualifier ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) = ma .getAnArgument ( )
97
+ or
98
+ mua .getAnArgument ( ) .( VarAccess ) .getVariable ( ) .getAnAccess ( ) = ma .getAnArgument ( )
99
+ ) and
100
+ isMDUpdateCall ( mua .getMethod ( ) )
101
+ )
99
102
}
100
103
}
101
104
105
+ /** Holds if a method invokes `md.update(salt)`. */
106
+ predicate isMDUpdateCall ( Callable caller ) {
107
+ caller instanceof MDUpdateMethod
108
+ or
109
+ exists ( Callable callee |
110
+ caller .polyCalls ( callee ) and
111
+ (
112
+ callee instanceof MDUpdateMethod or
113
+ isMDUpdateCall ( callee )
114
+ )
115
+ )
116
+ }
117
+
102
118
from DataFlow:: PathNode source , DataFlow:: PathNode sink , HashWithoutSaltConfiguration c
103
119
where c .hasFlowPath ( source , sink )
104
120
select sink .getNode ( ) , source , sink , "$@ is hashed without a salt." , source .getNode ( ) ,
0 commit comments