@@ -10,6 +10,7 @@ import semmle.code.java.frameworks.YamlBeans
10
10
import semmle.code.java.frameworks.HessianBurlap
11
11
import semmle.code.java.frameworks.Castor
12
12
import semmle.code.java.frameworks.apache.Lang
13
+ import semmle.code.java.Reflection
13
14
14
15
class ObjectInputStreamReadObjectMethod extends Method {
15
16
ObjectInputStreamReadObjectMethod ( ) {
@@ -246,21 +247,47 @@ private class UnsafeTypeConfig extends TaintTracking2::Configuration {
246
247
}
247
248
248
249
/**
249
- * Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
250
- *
251
- * Note any method that returns a `Class` or similar is assumed to propagate taint from all
252
- * of its arguments, so methods that accept user-controlled data but sanitize it or use it for some
253
- * completely different purpose before returning a `Class` could result in false positives.
250
+ * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class
251
+ * or at least looks like resolving a class.
254
252
*/
255
253
override predicate isAdditionalTaintStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
256
- exists ( MethodAccess ma , RefType returnType | returnType = ma .getMethod ( ) .getReturnType ( ) |
257
- returnType instanceof JacksonTypeDescriptorType and
258
- ma .getAnArgument ( ) = fromNode .asExpr ( ) and
259
- ma = toNode .asExpr ( )
260
- )
254
+ resolveClassStep ( fromNode , toNode ) or
255
+ looksLikeResolveClassStep ( fromNode , toNode )
261
256
}
262
257
}
263
258
259
+ /**
260
+ * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class.
261
+ */
262
+ private predicate resolveClassStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
263
+ exists ( ReflectiveClassIdentifierMethodAccess ma |
264
+ ma .getArgument ( 0 ) = fromNode .asExpr ( ) and
265
+ ma = toNode .asExpr ( )
266
+ )
267
+ }
268
+
269
+ /**
270
+ * Holds if `fromNode` to `toNode` is a dataflow step that looks like resolving a class.
271
+ * A method probably resolves a class if it is external, takes a string, returns a type descriptor
272
+ * and its name contains "resolve", "load", etc.
273
+ *
274
+ * Any method call that satisfies the rule above is assumed to propagate taint from its string arguments,
275
+ * so methods that accept user-controlled data but sanitize it or use it for some
276
+ * completely different purpose before returning a type descriptor could result in false positives.
277
+ */
278
+ private predicate looksLikeResolveClassStep ( DataFlow:: Node fromNode , DataFlow:: Node toNode ) {
279
+ exists ( MethodAccess ma , Method m , int i , Expr arg |
280
+ m = ma .getMethod ( ) and arg = ma .getArgument ( i )
281
+ |
282
+ m .getReturnType ( ) instanceof JacksonTypeDescriptorType and
283
+ m .getName ( ) .toLowerCase ( ) .regexpMatch ( "resolve|load|class|type" ) and
284
+ m .fromSource ( ) and
285
+ arg .getType ( ) instanceof TypeString and
286
+ arg = fromNode .asExpr ( ) and
287
+ ma = toNode .asExpr ( )
288
+ )
289
+ }
290
+
264
291
/**
265
292
* Holds if `fromNode` to `toNode` is a dataflow step that creates a Jackson parser.
266
293
*
0 commit comments