@@ -15,7 +15,6 @@ private import semmle.code.java.security.QueryInjection
15
15
private import semmle.code.java.security.RequestForgery
16
16
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
17
17
private import AutomodelJavaUtil as AutomodelJavaUtil
18
- private import AutomodelSharedGetCallable as AutomodelSharedGetCallable
19
18
import AutomodelSharedCharacteristics as SharedCharacteristics
20
19
import AutomodelEndpointTypes as AutomodelEndpointTypes
21
20
@@ -84,7 +83,7 @@ abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
84
83
/**
85
84
* Returns the callable that contains the endpoint.
86
85
*/
87
- abstract Callable getEnclosingCallable ( ) ;
86
+ abstract Callable getCallable ( ) ;
88
87
89
88
abstract Top asTop ( ) ;
90
89
@@ -106,7 +105,7 @@ class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParamete
106
105
107
106
override string getParamName ( ) { result = param .getName ( ) }
108
107
109
- override Callable getEnclosingCallable ( ) { result = param .getCallable ( ) }
108
+ override Callable getCallable ( ) { result = param .getCallable ( ) }
110
109
111
110
override Top asTop ( ) { result = param }
112
111
@@ -126,7 +125,7 @@ class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
126
125
127
126
override string getParamName ( ) { result = "this" }
128
127
129
- override Callable getEnclosingCallable ( ) { result = callable }
128
+ override Callable getCallable ( ) { result = callable }
130
129
131
130
override Top asTop ( ) { result = callable }
132
131
@@ -144,7 +143,7 @@ class ReturnValue extends FrameworkModeEndpoint, TReturnValue {
144
143
145
144
override string getParamName ( ) { none ( ) }
146
145
147
- override Callable getEnclosingCallable ( ) { result = callable }
146
+ override Callable getCallable ( ) { result = callable }
148
147
149
148
override Top asTop ( ) { result = callable }
150
149
@@ -163,7 +162,7 @@ class OverridableParameter extends FrameworkModeEndpoint, TOverridableParameter
163
162
164
163
override string getParamName ( ) { result = param .getName ( ) }
165
164
166
- override Callable getEnclosingCallable ( ) { result = method }
165
+ override Callable getCallable ( ) { result = method }
167
166
168
167
override Top asTop ( ) { result = param }
169
168
@@ -181,7 +180,7 @@ class OverridableQualifier extends FrameworkModeEndpoint, TOverridableQualifier
181
180
182
181
override string getParamName ( ) { result = "this" }
183
182
184
- override Callable getEnclosingCallable ( ) { result = m }
183
+ override Callable getCallable ( ) { result = m }
185
184
186
185
override Top asTop ( ) { result = m }
187
186
@@ -202,7 +201,9 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
202
201
203
202
class EndpointType = AutomodelEndpointTypes:: EndpointType ;
204
203
205
- class NegativeEndpointType = AutomodelEndpointTypes:: NegativeSinkType ;
204
+ class SinkType = AutomodelEndpointTypes:: SinkType ;
205
+
206
+ class SourceType = AutomodelEndpointTypes:: SourceType ;
206
207
207
208
class RelatedLocation = Location:: Top ;
208
209
@@ -244,8 +245,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
244
245
additional predicate sinkSpec (
245
246
Endpoint e , string package , string type , string name , string signature , string ext , string input
246
247
) {
247
- e .getEnclosingCallable ( ) .hasQualifiedName ( package , type , name ) and
248
- signature = ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) ) and
248
+ e .getCallable ( ) .hasQualifiedName ( package , type , name ) and
249
+ signature = ExternalFlow:: paramsString ( e .getCallable ( ) ) and
249
250
ext = "" and
250
251
input = e .getMaDInput ( )
251
252
}
@@ -254,8 +255,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
254
255
Endpoint e , string package , string type , string name , string signature , string ext ,
255
256
string output
256
257
) {
257
- e .getEnclosingCallable ( ) .hasQualifiedName ( package , type , name ) and
258
- signature = ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) ) and
258
+ e .getCallable ( ) .hasQualifiedName ( package , type , name ) and
259
+ signature = ExternalFlow:: paramsString ( e .getCallable ( ) ) and
259
260
ext = "" and
260
261
output = e .getMaDOutput ( )
261
262
}
@@ -267,10 +268,10 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
267
268
*/
268
269
RelatedLocation getRelatedLocation ( Endpoint e , RelatedLocationType type ) {
269
270
type = MethodDoc ( ) and
270
- result = e .getEnclosingCallable ( ) .( Documentable ) .getJavadoc ( )
271
+ result = e .getCallable ( ) .( Documentable ) .getJavadoc ( )
271
272
or
272
273
type = ClassDoc ( ) and
273
- result = e .getEnclosingCallable ( ) .getDeclaringType ( ) .( Documentable ) .getJavadoc ( )
274
+ result = e .getCallable ( ) .getDeclaringType ( ) .( Documentable ) .getJavadoc ( )
274
275
}
275
276
}
276
277
@@ -292,16 +293,27 @@ class FrameworkModeMetadataExtractor extends string {
292
293
293
294
predicate hasMetadata (
294
295
Endpoint e , string package , string type , string subtypes , string name , string signature ,
295
- string input , string output , string parameterName
296
+ string input , string output , string parameterName , string alreadyAiModeled ,
297
+ string extensibleType
296
298
) {
297
- ( if exists ( e .getParamName ( ) ) then parameterName = e .getParamName ( ) else parameterName = "" ) and
298
- name = e .getEnclosingCallable ( ) .getName ( ) and
299
- ( if exists ( e .getMaDInput ( ) ) then input = e .getMaDInput ( ) else input = "" ) and
300
- ( if exists ( e .getMaDOutput ( ) ) then output = e .getMaDOutput ( ) else output = "" ) and
301
- package = e .getEnclosingCallable ( ) .getDeclaringType ( ) .getPackage ( ) .getName ( ) and
302
- type = e .getEnclosingCallable ( ) .getDeclaringType ( ) .getErasure ( ) .( RefType ) .nestedName ( ) and
303
- subtypes = AutomodelJavaUtil:: considerSubtypes ( e .getEnclosingCallable ( ) ) .toString ( ) and
304
- signature = ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) )
299
+ exists ( Callable callable | e .getCallable ( ) = callable |
300
+ ( if exists ( e .getMaDInput ( ) ) then input = e .getMaDInput ( ) else input = "" ) and
301
+ ( if exists ( e .getMaDOutput ( ) ) then output = e .getMaDOutput ( ) else output = "" ) and
302
+ package = callable .getDeclaringType ( ) .getPackage ( ) .getName ( ) and
303
+ // we're using the erased types because the MaD convention is to not specify type parameters.
304
+ // Whether something is or isn't a sink doesn't usually depend on the type parameters.
305
+ type = callable .getDeclaringType ( ) .getErasure ( ) .( RefType ) .nestedName ( ) and
306
+ subtypes = AutomodelJavaUtil:: considerSubtypes ( callable ) .toString ( ) and
307
+ name = callable .getName ( ) and
308
+ signature = ExternalFlow:: paramsString ( callable ) and
309
+ ( if exists ( e .getParamName ( ) ) then parameterName = e .getParamName ( ) else parameterName = "" ) and
310
+ e .getExtensibleType ( ) = extensibleType
311
+ ) and
312
+ (
313
+ not CharacteristicsImpl:: isModeled ( e , _, extensibleType , _) and alreadyAiModeled = ""
314
+ or
315
+ CharacteristicsImpl:: isModeled ( e , _, extensibleType , alreadyAiModeled )
316
+ )
305
317
}
306
318
}
307
319
@@ -310,53 +322,79 @@ class FrameworkModeMetadataExtractor extends string {
310
322
*/
311
323
312
324
/**
313
- * A negative characteristic that indicates that an is-style boolean method is unexploitable even if it is a sink.
325
+ * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks,
326
+ * and its return value should not be considered a source.
314
327
*
315
328
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
316
329
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
317
330
* the dangerous/interesting thing, so we want the latter to be modeled as the sink.
318
331
*
319
332
* TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks
320
333
*/
321
- private class UnexploitableIsCharacteristic extends CharacteristicsImpl:: NotASinkCharacteristic {
334
+ private class UnexploitableIsCharacteristic extends CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic
335
+ {
322
336
UnexploitableIsCharacteristic ( ) { this = "unexploitable (is-style boolean method)" }
323
337
324
338
override predicate appliesToEndpoint ( Endpoint e ) {
325
- not FrameworkCandidatesImpl:: isSink ( e , _, _) and
326
- e .getEnclosingCallable ( ) .getName ( ) .matches ( "is%" ) and
327
- e .getEnclosingCallable ( ) .getReturnType ( ) instanceof BooleanType
339
+ e .getCallable ( ) .getName ( ) .matches ( "is%" ) and
340
+ e .getCallable ( ) .getReturnType ( ) instanceof BooleanType and
341
+ (
342
+ e .getExtensibleType ( ) = "sinkModel" and
343
+ not FrameworkCandidatesImpl:: isSink ( e , _, _)
344
+ or
345
+ e .getExtensibleType ( ) = "sourceModel" and
346
+ not FrameworkCandidatesImpl:: isSource ( e , _, _) and
347
+ e .getMaDOutput ( ) = "ReturnValue"
348
+ )
328
349
}
329
350
}
330
351
331
352
/**
332
- * A negative characteristic that indicates that an existence-checking boolean method is unexploitable even if it is a
333
- * sink .
353
+ * A negative characteristic that indicates that parameters of an existence-checking boolean method should not be
354
+ * considered sinks, and its return value should not be considered a source .
334
355
*
335
356
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
336
357
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
337
358
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
338
359
*/
339
- private class UnexploitableExistsCharacteristic extends CharacteristicsImpl:: NotASinkCharacteristic {
360
+ private class UnexploitableExistsCharacteristic extends CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic
361
+ {
340
362
UnexploitableExistsCharacteristic ( ) { this = "unexploitable (existence-checking boolean method)" }
341
363
342
364
override predicate appliesToEndpoint ( Endpoint e ) {
343
- not FrameworkCandidatesImpl:: isSink ( e , _, _) and
344
365
exists ( Callable callable |
345
- callable = e .getEnclosingCallable ( ) and
366
+ callable = e .getCallable ( ) and
346
367
callable .getName ( ) .toLowerCase ( ) = [ "exists" , "notexists" ] and
347
368
callable .getReturnType ( ) instanceof BooleanType
369
+ |
370
+ e .getExtensibleType ( ) = "sinkModel" and
371
+ not FrameworkCandidatesImpl:: isSink ( e , _, _)
372
+ or
373
+ e .getExtensibleType ( ) = "sourceModel" and
374
+ not FrameworkCandidatesImpl:: isSource ( e , _, _) and
375
+ e .getMaDOutput ( ) = "ReturnValue"
348
376
)
349
377
}
350
378
}
351
379
352
380
/**
353
- * A negative characteristic that indicates that an endpoint is an argument to an exception, which is not a sink.
381
+ * A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks,
382
+ * and its return value should not be considered a source.
354
383
*/
355
- private class ExceptionCharacteristic extends CharacteristicsImpl:: NotASinkCharacteristic {
384
+ private class ExceptionCharacteristic extends CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic
385
+ {
356
386
ExceptionCharacteristic ( ) { this = "exception" }
357
387
358
388
override predicate appliesToEndpoint ( Endpoint e ) {
359
- e .getEnclosingCallable ( ) .getDeclaringType ( ) .getASupertype * ( ) instanceof TypeThrowable
389
+ e .getCallable ( ) .getDeclaringType ( ) .getASupertype * ( ) instanceof TypeThrowable and
390
+ (
391
+ e .getExtensibleType ( ) = "sinkModel" and
392
+ not FrameworkCandidatesImpl:: isSink ( e , _, _)
393
+ or
394
+ e .getExtensibleType ( ) = "sourceModel" and
395
+ not FrameworkCandidatesImpl:: isSource ( e , _, _) and
396
+ e .getMaDOutput ( ) = "ReturnValue"
397
+ )
360
398
}
361
399
}
362
400
@@ -368,6 +406,6 @@ private class NotAModelApi extends CharacteristicsImpl::UninterestingToModelChar
368
406
NotAModelApi ( ) { this = "not a model API" }
369
407
370
408
override predicate appliesToEndpoint ( Endpoint e ) {
371
- not e .getEnclosingCallable ( ) instanceof ModelExclusions:: ModelApi
409
+ not e .getCallable ( ) instanceof ModelExclusions:: ModelApi
372
410
}
373
411
}
0 commit comments