Skip to content

Commit 815602d

Browse files
committed
C#: Re-factor some of the data flow configurations used by the UnsafeDeserializationQuery to use the new API.
1 parent a9cf688 commit 815602d

File tree

2 files changed

+146
-26
lines changed

2 files changed

+146
-26
lines changed

csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll

Lines changed: 128 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ abstract class Sanitizer extends DataFlow::Node { }
4747
private class RemoteSource extends Source instanceof RemoteFlowSource { }
4848

4949
/**
50+
* DEPRECATED: Use `TaintToObjectMethodTracking` instead.
51+
*
5052
* User input to object method call deserialization flow tracking.
5153
*/
52-
class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration {
54+
deprecated class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration {
5355
TaintToObjectMethodTrackingConfig() { this = "TaintToObjectMethodTrackingConfig" }
5456

5557
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -60,9 +62,27 @@ class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration {
6062
}
6163

6264
/**
65+
* User input to object method call deserialization flow tracking configuration.
66+
*/
67+
private module TaintToObjectMethodTrackingConfig implements DataFlow::ConfigSig {
68+
predicate isSource(DataFlow::Node source) { source instanceof Source }
69+
70+
predicate isSink(DataFlow::Node sink) { sink instanceof InstanceMethodSink }
71+
72+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
73+
}
74+
75+
/**
76+
* User input to object method call deserialization flow tracking module.
77+
*/
78+
module TaintToObjectMethodTracking = TaintTracking::Global<TaintToObjectMethodTrackingConfig>;
79+
80+
/**
81+
* DEPRECATED: Use `JsonConvertTracking` instead.
82+
*
6383
* User input to `JsonConvert` call deserialization flow tracking.
6484
*/
65-
class JsonConvertTrackingConfig extends TaintTracking::Configuration {
85+
deprecated class JsonConvertTrackingConfig extends TaintTracking::Configuration {
6686
JsonConvertTrackingConfig() { this = "JsonConvertTrackingConfig" }
6787

6888
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -74,6 +94,24 @@ class JsonConvertTrackingConfig extends TaintTracking::Configuration {
7494
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
7595
}
7696

97+
/**
98+
* User input to `JsonConvert` call deserialization flow tracking configuration.
99+
*/
100+
private module JsonConvertTrackingConfig implements DataFlow::ConfigSig {
101+
predicate isSource(DataFlow::Node source) { source instanceof Source }
102+
103+
predicate isSink(DataFlow::Node sink) {
104+
sink instanceof NewtonsoftJsonConvertDeserializeObjectMethodSink
105+
}
106+
107+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
108+
}
109+
110+
/**
111+
* User input to `JsonConvert` call deserialization flow tracking module.
112+
*/
113+
module JsonConvertTracking = TaintTracking::Global<JsonConvertTrackingConfig>;
114+
77115
/**
78116
* DEPRECATED: Use `TypeNameTracking` instead.
79117
*
@@ -186,9 +224,12 @@ private module TypeNameTrackingConfig implements DataFlow::ConfigSig {
186224
module TypeNameTracking = DataFlow::Global<TypeNameTrackingConfig>;
187225

188226
/**
227+
* DEPRECATED: Use `TaintToConstructorOrStaticMethodTracking` instead.
228+
*
189229
* User input to static method or constructor call deserialization flow tracking.
190230
*/
191-
class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration {
231+
deprecated class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration
232+
{
192233
TaintToConstructorOrStaticMethodTrackingConfig() {
193234
this = "TaintToConstructorOrStaticMethodTrackingConfig"
194235
}
@@ -201,9 +242,28 @@ class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Conf
201242
}
202243

203244
/**
245+
* User input to static method or constructor call deserialization flow tracking configuration.
246+
*/
247+
private module TaintToConstructorOrStaticMethodTrackingConfig implements DataFlow::ConfigSig {
248+
predicate isSource(DataFlow::Node source) { source instanceof Source }
249+
250+
predicate isSink(DataFlow::Node sink) { sink instanceof ConstructorOrStaticMethodSink }
251+
252+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
253+
}
254+
255+
/**
256+
* User input to static method or constructor call deserialization flow tracking module.
257+
*/
258+
module TaintToConstructorOrStaticMethodTracking =
259+
TaintTracking::Global<TaintToConstructorOrStaticMethodTrackingConfig>;
260+
261+
/**
262+
* DEPRECATED: Use `TaintToObjectTypeTracking` instead.
263+
*
204264
* User input to instance type flow tracking.
205265
*/
206-
class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration {
266+
deprecated class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration {
207267
TaintToObjectTypeTrackingConfig() { this = "TaintToObjectTypeTrackingConfig" }
208268

209269
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -234,9 +294,47 @@ class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration {
234294
}
235295

236296
/**
297+
* User input to instance type flow tracking config.
298+
*/
299+
private module TaintToObjectTypeTrackingConfig implements DataFlow::ConfigSig {
300+
predicate isSource(DataFlow::Node source) { source instanceof Source }
301+
302+
predicate isSink(DataFlow::Node sink) {
303+
exists(MethodCall mc |
304+
mc.getTarget() instanceof UnsafeDeserializer and
305+
sink.asExpr() = mc.getQualifier()
306+
)
307+
}
308+
309+
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
310+
exists(MethodCall mc, Method m |
311+
m = mc.getTarget() and
312+
m.getDeclaringType().hasQualifiedName("System", "Type") and
313+
m.hasName("GetType") and
314+
m.isStatic() and
315+
n1.asExpr() = mc.getArgument(0) and
316+
n2.asExpr() = mc
317+
)
318+
or
319+
exists(ObjectCreation oc |
320+
n1.asExpr() = oc.getAnArgument() and
321+
n2.asExpr() = oc and
322+
oc.getObjectType() instanceof StrongTypeDeserializer
323+
)
324+
}
325+
}
326+
327+
/**
328+
* User input to instance type flow tracking module.
329+
*/
330+
module TaintToObjectTypeTracking = TaintTracking::Global<TaintToObjectTypeTrackingConfig>;
331+
332+
/**
333+
* DEPRECATED: Use `WeakTypeCreationToUsageTracking` instead.
334+
*
237335
* Unsafe deserializer creation to usage tracking config.
238336
*/
239-
class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuration {
337+
deprecated class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuration {
240338
WeakTypeCreationToUsageTrackingConfig() { this = "DeserializerCreationToUsageTrackingConfig" }
241339

242340
override predicate isSource(DataFlow::Node source) {
@@ -254,6 +352,31 @@ class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuratio
254352
}
255353
}
256354

355+
/**
356+
* Unsafe deserializer creation to usage tracking config.
357+
*/
358+
private module WeakTypeCreationToUsageTrackingConfig implements DataFlow::ConfigSig {
359+
predicate isSource(DataFlow::Node source) {
360+
exists(ObjectCreation oc |
361+
oc.getObjectType() instanceof WeakTypeDeserializer and
362+
source.asExpr() = oc
363+
)
364+
}
365+
366+
predicate isSink(DataFlow::Node sink) {
367+
exists(MethodCall mc |
368+
mc.getTarget() instanceof UnsafeDeserializer and
369+
sink.asExpr() = mc.getQualifier()
370+
)
371+
}
372+
}
373+
374+
/**
375+
* Unsafe deserializer creation to usage tracking module.
376+
*/
377+
module WeakTypeCreationToUsageTracking =
378+
TaintTracking::Global<WeakTypeCreationToUsageTrackingConfig>;
379+
257380
/**
258381
* Safe deserializer creation to usage tracking config.
259382
*/

csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,40 @@
1313

1414
import csharp
1515
import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery
16-
import DataFlow::PathGraph
16+
import Flow::PathGraph
1717

18-
from DataFlow::PathNode userInput, DataFlow::PathNode deserializeCallArg
18+
module Flow =
19+
DataFlow::MergePathGraph3<TaintToObjectMethodTracking::PathNode,
20+
TaintToConstructorOrStaticMethodTracking::PathNode, JsonConvertTracking::PathNode,
21+
TaintToObjectMethodTracking::PathGraph, TaintToConstructorOrStaticMethodTracking::PathGraph,
22+
JsonConvertTracking::PathGraph>;
23+
24+
from Flow::PathNode userInput, Flow::PathNode deserializeCallArg
1925
where
20-
exists(TaintToObjectMethodTrackingConfig taintTracking |
21-
// all flows from user input to deserialization with weak and strong type serializers
22-
taintTracking.hasFlowPath(userInput, deserializeCallArg)
23-
) and
26+
// all flows from user input to deserialization with weak and strong type serializers
27+
TaintToObjectMethodTracking::flowPath(userInput.asPathNode1(), deserializeCallArg.asPathNode1()) and
2428
// intersect with strong types, but user controlled or weak types deserialization usages
2529
(
26-
exists(
27-
DataFlow::Node weakTypeUsage,
28-
WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking, MethodCall mc
29-
|
30-
weakTypeDeserializerTracking.hasFlowTo(weakTypeUsage) and
30+
exists(DataFlow::Node weakTypeUsage, MethodCall mc |
31+
WeakTypeCreationToUsageTracking::flowTo(weakTypeUsage) and
3132
mc.getQualifier() = weakTypeUsage.asExpr() and
3233
mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
3334
)
3435
or
35-
exists(
36-
TaintToObjectTypeTrackingConfig userControlledTypeTracking, DataFlow::Node taintedTypeUsage,
37-
MethodCall mc
38-
|
39-
userControlledTypeTracking.hasFlowTo(taintedTypeUsage) and
36+
exists(DataFlow::Node taintedTypeUsage, MethodCall mc |
37+
TaintToObjectTypeTracking::flowTo(taintedTypeUsage) and
4038
mc.getQualifier() = taintedTypeUsage.asExpr() and
4139
mc.getAnArgument() = deserializeCallArg.getNode().asExpr()
4240
)
4341
)
4442
or
4543
// no type check needed - straightforward taint -> sink
46-
exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 |
47-
taintTracking2.hasFlowPath(userInput, deserializeCallArg)
48-
)
44+
TaintToConstructorOrStaticMethodTracking::flowPath(userInput.asPathNode2(),
45+
deserializeCallArg.asPathNode2())
4946
or
5047
// JsonConvert static method call, but with additional unsafe typename tracking
51-
exists(JsonConvertTrackingConfig taintTrackingJsonConvert, DataFlow::Node settingsCallArg |
52-
taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and
48+
exists(DataFlow::Node settingsCallArg |
49+
JsonConvertTracking::flowPath(userInput.asPathNode3(), deserializeCallArg.asPathNode3()) and
5350
TypeNameTracking::flow(_, settingsCallArg) and
5451
deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent()
5552
)

0 commit comments

Comments
 (0)