@@ -46,7 +46,7 @@ module HardcodedKeys {
4646 /**
4747 * A hardcoded string literal as a source for JWT token signing vulnerabilities.
4848 */
49- class HardcodedStringSource extends Source {
49+ private class HardcodedStringSource extends Source {
5050 HardcodedStringSource ( ) {
5151 this .asExpr ( ) instanceof StringLit and
5252 not ( isTestCode ( this .asExpr ( ) ) or isDemoCode ( this .asExpr ( ) ) )
@@ -166,7 +166,7 @@ module HardcodedKeys {
166166 }
167167
168168 /** Mark an empty string returned with an error as a sanitizer */
169- class EmptyErrorSanitizer extends Sanitizer {
169+ private class EmptyErrorSanitizer extends Sanitizer {
170170 EmptyErrorSanitizer ( ) {
171171 exists ( ReturnStmt r , DataFlow:: CallNode c |
172172 c .getTarget ( ) .hasQualifiedName ( "errors" , "New" ) and
@@ -178,7 +178,7 @@ module HardcodedKeys {
178178 }
179179
180180 /** Mark any formatting string call as a sanitizer */
181- class FormattingSanitizer extends Sanitizer {
181+ private class FormattingSanitizer extends Sanitizer {
182182 FormattingSanitizer ( ) { exists ( Formatting:: StringFormatCall s | s .getAResult ( ) = this ) }
183183 }
184184
@@ -188,19 +188,6 @@ module HardcodedKeys {
188188 */
189189 private class RandSliceSanitizer extends Sanitizer {
190190 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
204191 // Sanitize flows like this:
205192 // func GenerateCryptoString(n int) (string, error) {
206193 // const chars = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
@@ -215,12 +202,20 @@ module HardcodedKeys {
215202 // return string(ret), nil
216203 // }
217204 exists (
218- DataFlow:: CallNode randint , DataFlow:: MethodCallNode bigint , DataFlow:: ElementReadNode r
205+ DataFlow:: CallNode randint , string name , DataFlow:: ElementReadNode r , DataFlow:: Node index
219206 |
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 )
224219 )
225220 or
226221 // Sanitize flows like :
@@ -232,29 +227,49 @@ module HardcodedKeys {
232227 // }
233228 // return string(bytes)
234229 // }
235- exists ( DataFlow:: CallNode randread , DataFlow:: Node rand , DataFlow :: ElementReadNode r |
230+ exists ( DataFlow:: CallNode randread , DataFlow:: Node rand |
236231 randread .getTarget ( ) .hasQualifiedName ( "crypto/rand" , "Read" ) and
237232 TaintTracking:: localTaint ( any ( DataFlow:: PostUpdateNode pun |
238233 pun .getPreUpdateNode ( ) = randread .getArgument ( 0 )
239234 ) , 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 )
254236 )
255237 }
256238 }
257239
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+
258273 /**
259274 * A configuration depicting taint flow for studying JWT token signing vulnerabilities.
260275 */
@@ -267,6 +282,8 @@ module HardcodedKeys {
267282
268283 override predicate isSanitizer ( DataFlow:: Node sanitizer ) { sanitizer instanceof Sanitizer }
269284
285+ // override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
286+ // }
270287 override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
271288 guard instanceof SanitizerGuard
272289 }
0 commit comments