@@ -14,10 +14,7 @@ import ModelGeneratorUtils
1414
1515string captureFlow ( TargetAPI api ) {
1616 result = captureQualifierFlow ( api ) or
17- result = captureParameterFlowToReturnValue ( api ) or
18- result = captureFieldFlowIn ( api ) or
19- result = captureParameterToParameterFlow ( api ) or
20- result = captureFieldFlow ( api )
17+ result = captureThroughFlow ( api )
2118}
2219
2320/**
@@ -40,21 +37,51 @@ string captureQualifierFlow(TargetAPI api) {
4037 result = asValueModel ( api , "Argument[-1]" , "ReturnValue" )
4138}
4239
43- class FieldToReturnConfig extends TaintTracking:: Configuration {
44- FieldToReturnConfig ( ) { this = "FieldToReturnConfig" }
40+ class TaintRead extends DataFlow:: FlowState {
41+ TaintRead ( ) { this = "TaintRead" }
42+ }
43+
44+ class TaintStore extends DataFlow:: FlowState {
45+ TaintStore ( ) { this = "TaintStore" }
46+ }
4547
46- override predicate isSource ( DataFlow:: Node source ) {
47- source instanceof DataFlow:: InstanceParameterNode
48+ class ThroughFlowConfig extends TaintTracking:: Configuration {
49+ ThroughFlowConfig ( ) { this = "ThroughFlowConfig" }
50+
51+ override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowState state ) {
52+ source instanceof DataFlow:: ParameterNode and
53+ source .getEnclosingCallable ( ) instanceof TargetAPI and
54+ state instanceof TaintRead
4855 }
4956
50- override predicate isSink ( DataFlow:: Node sink ) {
57+ override predicate isSink ( DataFlow:: Node sink , DataFlow :: FlowState state ) {
5158 sink instanceof ReturnNodeExt and
5259 not sink .( ReturnNode ) .asExpr ( ) .( ThisAccess ) .isOwnInstanceAccess ( ) and
53- not exists ( captureQualifierFlow ( sink .asExpr ( ) .getEnclosingCallable ( ) ) )
60+ not exists ( captureQualifierFlow ( sink .asExpr ( ) .getEnclosingCallable ( ) ) ) and
61+ ( state instanceof TaintRead or state instanceof TaintStore )
62+ }
63+
64+ override predicate isAdditionalFlowStep (
65+ DataFlow:: Node node1 , DataFlow:: FlowState state1 , DataFlow:: Node node2 ,
66+ DataFlow:: FlowState state2
67+ ) {
68+ exists ( TypedContent tc |
69+ store ( node1 , tc , node2 , _) and
70+ isRelevantContent ( tc .getContent ( ) ) and
71+ ( state1 instanceof TaintRead or state1 instanceof TaintStore ) and
72+ state2 instanceof TaintStore
73+ )
74+ or
75+ exists ( DataFlow:: Content c |
76+ readStep ( node1 , c , node2 ) and
77+ isRelevantContent ( c ) and
78+ state1 instanceof TaintRead and
79+ state2 instanceof TaintRead
80+ )
5481 }
5582
56- override predicate isAdditionalTaintStep ( DataFlow:: Node node1 , DataFlow :: Node node2 ) {
57- isRelevantTaintStep ( node1 , node2 )
83+ override predicate isSanitizer ( DataFlow:: Node n ) {
84+ exists ( Type t | t = n . getType ( ) and not isRelevantType ( t ) )
5885 }
5986
6087 override DataFlow:: FlowFeature getAFeature ( ) {
@@ -63,8 +90,12 @@ class FieldToReturnConfig extends TaintTracking::Configuration {
6390}
6491
6592/**
66- * Capture APIs that return tainted instance data.
67- * Example of an API that returns tainted instance data:
93+ * Capture APIs that transfer taint from an input parameter to an output return
94+ * value or parameter.
95+ * Allows a sequence of read steps followed by a sequence of store steps.
96+ *
97+ * Examples:
98+ *
6899 * ```
69100 * public class Foo {
70101 * private String tainted;
@@ -83,48 +114,7 @@ class FieldToReturnConfig extends TaintTracking::Configuration {
83114 * p;Foo;true;returnsTainted;;Argument[-1];ReturnValue;taint
84115 * p;Foo;true;putsTaintIntoParameter;(List);Argument[-1];Argument[0];taint
85116 * ```
86- */
87- string captureFieldFlow ( TargetAPI api ) {
88- exists ( FieldToReturnConfig config , ReturnNodeExt returnNodeExt |
89- config .hasFlow ( _, returnNodeExt ) and
90- returnNodeExt .getEnclosingCallable ( ) = api and
91- not api .getDeclaringType ( ) instanceof EnumType and
92- isRelevantType ( returnNodeExt .getType ( ) )
93- |
94- result = asTaintModel ( api , "Argument[-1]" , returnNodeAsOutput ( api , returnNodeExt ) )
95- )
96- }
97-
98- class ParameterToFieldConfig extends TaintTracking:: Configuration {
99- ParameterToFieldConfig ( ) { this = "ParameterToFieldConfig" }
100-
101- override predicate isSource ( DataFlow:: Node source ) {
102- source instanceof DataFlow:: ParameterNode and
103- isRelevantType ( source .getType ( ) )
104- }
105-
106- override predicate isSink ( DataFlow:: Node sink ) {
107- thisAccess ( sink .( DataFlow:: PostUpdateNode ) .getPreUpdateNode ( ) )
108- }
109-
110- override predicate isAdditionalTaintStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
111- store ( node1 , _, node2 , _)
112- }
113-
114- override DataFlow:: FlowFeature getAFeature ( ) {
115- result instanceof DataFlow:: FeatureEqualSourceSinkCallContext
116- }
117- }
118-
119- private predicate thisAccess ( DataFlow:: Node n ) {
120- n .asExpr ( ) .( InstanceAccess ) .isOwnInstanceAccess ( )
121- or
122- n .( DataFlow:: ImplicitInstanceAccess ) .getInstanceAccess ( ) instanceof OwnInstanceAccess
123- }
124-
125- /**
126- * Captures APIs that accept input and store them in a field.
127- * Example:
117+ *
128118 * ```
129119 * public class Foo {
130120 * private String tainted;
@@ -134,96 +124,38 @@ private predicate thisAccess(DataFlow::Node n) {
134124 * ```
135125 * Captured Model:
136126 * `p;Foo;true;doSomething;(String);Argument[0];Argument[-1];taint`
137- */
138- string captureFieldFlowIn ( TargetAPI api ) {
139- exists ( DataFlow:: Node source , ParameterToFieldConfig config |
140- config .hasFlow ( source , _) and
141- source .asParameter ( ) .getCallable ( ) = api
142- |
143- result =
144- asTaintModel ( api , "Argument[" + source .asParameter ( ) .getPosition ( ) + "]" , "Argument[-1]" )
145- )
146- }
147-
148- class ParameterToReturnValueTaintConfig extends TaintTracking:: Configuration {
149- ParameterToReturnValueTaintConfig ( ) { this = "ParameterToReturnValueTaintConfig" }
150-
151- override predicate isSource ( DataFlow:: Node source ) {
152- exists ( TargetAPI api |
153- api = source .asParameter ( ) .getCallable ( ) and
154- isRelevantType ( api .getReturnType ( ) ) and
155- isRelevantType ( source .asParameter ( ) .getType ( ) )
156- )
157- }
158-
159- override predicate isSink ( DataFlow:: Node sink ) { sink instanceof ReturnNode }
160-
161- // consider store steps to track taint across objects to model factory methods returning tainted objects
162- override predicate isAdditionalTaintStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
163- store ( node1 , _, node2 , _)
164- }
165-
166- override DataFlow:: FlowFeature getAFeature ( ) {
167- result instanceof DataFlow:: FeatureEqualSourceSinkCallContext
168- }
169- }
170-
171- predicate paramFlowToReturnValueExists ( Parameter p ) {
172- exists ( ParameterToReturnValueTaintConfig config , ReturnStmt rtn |
173- config .hasFlow ( DataFlow:: parameterNode ( p ) , DataFlow:: exprNode ( rtn .getResult ( ) ) )
174- )
175- }
176-
177- /**
178- * Capture APIs that return (parts of) data passed in as a parameter.
179- * Example:
127+ *
180128 * ```
181129 * public class Foo {
182- *
183130 * public String returnData(String tainted) {
184131 * return tainted.substring(0,10)
185132 * }
186133 * }
187134 * ```
188135 * Captured Model:
189- * ```
190- * p;Foo;true;returnData;;Argument[0];ReturnValue;taint
191- * ```
192- */
193- string captureParameterFlowToReturnValue ( TargetAPI api ) {
194- exists ( Parameter p |
195- p = api .getAParameter ( ) and
196- paramFlowToReturnValueExists ( p )
197- |
198- result = asTaintModel ( api , parameterAccess ( p ) , "ReturnValue" )
199- )
200- }
201-
202- /**
203- * Capture APIs that pass tainted data from a parameter to a parameter.
204- * Example:
136+ * `p;Foo;true;returnData;;Argument[0];ReturnValue;taint`
137+ *
205138 * ```
206139 * public class Foo {
207- *
208140 * public void addToList(String tainted, List<String> foo) {
209141 * foo.add(tainted);
210142 * }
211143 * }
212144 * ```
213145 * Captured Model:
214- * ```
215- * p;Foo;true;addToList;;Argument[0];Argument[1];taint
216- * ```
146+ * `p;Foo;true;addToList;;Argument[0];Argument[1];taint`
217147 */
218- string captureParameterToParameterFlow ( TargetAPI api ) {
219- exists ( DataFlow:: ParameterNode source , DataFlow:: PostUpdateNode sink |
220- source .getEnclosingCallable ( ) = api and
221- sink .getPreUpdateNode ( ) .asExpr ( ) = api .getAParameter ( ) .getAnAccess ( ) and
222- TaintTracking:: localTaint ( source , sink )
148+ string captureThroughFlow ( TargetAPI api ) {
149+ exists (
150+ ThroughFlowConfig config , DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt , string input ,
151+ string output
223152 |
224- result =
225- asTaintModel ( api , parameterAccess ( source .asParameter ( ) ) ,
226- parameterAccess ( sink .getPreUpdateNode ( ) .asExpr ( ) .( VarAccess ) .getVariable ( ) ) )
153+ config .hasFlow ( p , returnNodeExt ) and
154+ returnNodeExt .getEnclosingCallable ( ) = api and
155+ input = parameterNodeAsInput ( p ) and
156+ output = returnNodeAsOutput ( returnNodeExt ) and
157+ input != output and
158+ result = asTaintModel ( api , input , output )
227159 )
228160}
229161
0 commit comments