Skip to content

Commit 72e0235

Browse files
authored
Merge pull request #12723 from michaelnebel/csharp/refactordataflow2
C#: Re-factor queries to use the new API.
2 parents d7feaf4 + 3a316f1 commit 72e0235

22 files changed

+289
-77
lines changed

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,26 +90,38 @@ class ExternalApiDataNode extends DataFlow::Node {
9090
/** DEPRECATED: Alias for ExternalApiDataNode */
9191
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
9292

93-
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
94-
class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
93+
/**
94+
* DEPRECATED: Use `RemoteSourceToExternalApi` instead.
95+
*
96+
* A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s.
97+
*/
98+
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
9599
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
96100

97101
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
98102

99103
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
100104
}
101105

106+
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
107+
private module RemoteSourceToExternalApiConfig implements DataFlow::ConfigSig {
108+
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
109+
110+
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
111+
}
112+
113+
/** A module for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
114+
module RemoteSourceToExternalApi = TaintTracking::Global<RemoteSourceToExternalApiConfig>;
115+
102116
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
103117
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
104118

105119
/** A node representing untrusted data being passed to an external API. */
106120
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
107-
private UntrustedDataToExternalApiConfig c;
108-
109-
UntrustedExternalApiDataNode() { c.hasFlow(_, this) }
121+
UntrustedExternalApiDataNode() { RemoteSourceToExternalApi::flow(_, this) }
110122

111123
/** Gets a source of untrusted data which is passed to this external API data node. */
112-
DataFlow::Node getAnUntrustedSource() { c.hasFlow(result, this) }
124+
DataFlow::Node getAnUntrustedSource() { RemoteSourceToExternalApi::flow(result, this) }
113125
}
114126

115127
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ abstract class Sink extends DataFlow::ExprNode {
3838
abstract class Sanitizer extends DataFlow::ExprNode { }
3939

4040
/**
41+
* DEPRECATED: Use `HardcodedCredentials` instead.
42+
*
4143
* A taint-tracking configuration for hard coded credentials.
4244
*/
43-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
45+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
4446
TaintTrackingConfiguration() { this = "HardcodedCredentials" }
4547

4648
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -75,6 +77,56 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
7577
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
7678
}
7779

80+
/**
81+
* A taint-tracking configuration for hard coded credentials.
82+
*/
83+
private module HardcodedCredentialsConfig implements DataFlow::ConfigSig {
84+
predicate isSource(DataFlow::Node source) { source instanceof Source }
85+
86+
predicate isSink(DataFlow::Node sink) {
87+
sink instanceof Sink and
88+
// Ignore values that are ultimately returned by mocks, as they don't represent "real"
89+
// credentials.
90+
not any(ReturnedByMockObject mock).getAMemberInitializationValue() = sink.asExpr() and
91+
not any(ReturnedByMockObject mock).getAnArgument() = sink.asExpr()
92+
}
93+
94+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
95+
}
96+
97+
/**
98+
* A taint-tracking module for hard coded credentials.
99+
*/
100+
module HardcodedCredentials {
101+
import TaintTracking::Global<HardcodedCredentialsConfig> as Super
102+
import Super
103+
104+
/**
105+
* Holds if data can flow from `source` to `sink`.
106+
*
107+
* The corresponding paths are generated from the end-points and the graph
108+
* included in the module `PathGraph`.
109+
*/
110+
predicate flowPath(HardcodedCredentials::PathNode source, HardcodedCredentials::PathNode sink) {
111+
Super::flowPath(source, sink) and
112+
// Exclude hard-coded credentials in tests if they only flow to calls to methods with a name
113+
// like "Add*" "Create*" or "Update*". The rationale is that hard-coded credentials within
114+
// tests that are only used for creating or setting values within tests are unlikely to
115+
// represent credentials to some accessible system.
116+
not (
117+
source.getNode().asExpr().getFile() instanceof TestFile and
118+
exists(MethodCall createOrAddCall, string createOrAddMethodName |
119+
createOrAddMethodName.matches("Update%") or
120+
createOrAddMethodName.matches("Create%") or
121+
createOrAddMethodName.matches("Add%")
122+
|
123+
createOrAddCall.getTarget().hasName(createOrAddMethodName) and
124+
createOrAddCall.getAnArgument() = sink.getNode().asExpr()
125+
)
126+
)
127+
}
128+
}
129+
78130
/**
79131
* A string literal that is not empty.
80132
*/

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2525
abstract class Sanitizer extends DataFlow::ExprNode { }
2626

2727
/**
28+
* DEPRECATED: Use `LdapInjection` instead.
29+
*
2830
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
2931
*/
30-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
32+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3133
TaintTrackingConfiguration() { this = "LDAPInjection" }
3234

3335
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,32 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3739
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3840
}
3941

42+
/**
43+
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
44+
*/
45+
module LdapInjectionConfig implements DataFlow::ConfigSig {
46+
/**
47+
* Holds if `source` is a relevant data flow source.
48+
*/
49+
predicate isSource(DataFlow::Node source) { source instanceof Source }
50+
51+
/**
52+
* Holds if `sink` is a relevant data flow sink.
53+
*/
54+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
55+
56+
/**
57+
* Holds if data flow through `node` is prohibited. This completely removes
58+
* `node` from the data flow graph.
59+
*/
60+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
61+
}
62+
63+
/**
64+
* A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries.
65+
*/
66+
module LdapInjection = TaintTracking::Global<LdapInjectionConfig>;
67+
4068
/** A source of remote user input. */
4169
class RemoteSource extends Source instanceof RemoteFlowSource { }
4270

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2525
abstract class Sanitizer extends DataFlow::ExprNode { }
2626

2727
/**
28+
* DEPRECATED: Use `LogForging` instead.
29+
*
2830
* A taint-tracking configuration for untrusted user input used in log entries.
2931
*/
30-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
32+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3133
TaintTrackingConfiguration() { this = "LogForging" }
3234

3335
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3739
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3840
}
3941

42+
/**
43+
* A taint-tracking configuration for untrusted user input used in log entries.
44+
*/
45+
private module LogForgingConfig implements DataFlow::ConfigSig {
46+
predicate isSource(DataFlow::Node source) { source instanceof Source }
47+
48+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
49+
50+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
51+
}
52+
53+
/**
54+
* A taint-tracking module for untrusted user input used in log entries.
55+
*/
56+
module LogForging = TaintTracking::Global<LogForgingConfig>;
57+
4058
/** A source of remote user input. */
4159
private class RemoteSource extends Source instanceof RemoteFlowSource { }
4260

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ abstract class Sink extends DataFlow::ExprNode {
2929
abstract class Sanitizer extends DataFlow::ExprNode { }
3030

3131
/**
32+
* DEPRECATED: Use `MissingXxmlValidation` instead.
33+
*
3234
* A taint-tracking configuration for untrusted user input processed as XML without validation against a
3335
* known schema.
3436
*/
35-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
37+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3638
TaintTrackingConfiguration() { this = "MissingXMLValidation" }
3739

3840
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -42,6 +44,24 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
4244
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
4345
}
4446

47+
/**
48+
* A taint-tracking configuration for untrusted user input processed as XML without validation against a
49+
* known schema.
50+
*/
51+
private module MissingXmlValidationConfig implements DataFlow::ConfigSig {
52+
predicate isSource(DataFlow::Node source) { source instanceof Source }
53+
54+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
55+
56+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
57+
}
58+
59+
/**
60+
* A taint-tracking module for untrusted user input processed as XML without validation against a
61+
* known schema.
62+
*/
63+
module MissingXmlValidation = TaintTracking::Global<MissingXmlValidationConfig>;
64+
4565
/** A source of remote user input. */
4666
class RemoteSource extends Source instanceof RemoteFlowSource { }
4767

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2525
abstract class Sanitizer extends DataFlow::ExprNode { }
2626

2727
/**
28+
* DEPRECATED: Use `ReDoS` instead.
29+
*
2830
* A taint-tracking configuration for untrusted user input used in dangerous regular expression operations.
2931
*/
30-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
32+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3133
TaintTrackingConfiguration() { this = "ReDoS" }
3234

3335
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3739
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3840
}
3941

42+
/**
43+
* A taint-tracking configuration for untrusted user input used in dangerous regular expression operations.
44+
*/
45+
private module ReDoSConfig implements DataFlow::ConfigSig {
46+
predicate isSource(DataFlow::Node source) { source instanceof Source }
47+
48+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
49+
50+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
51+
}
52+
53+
/**
54+
* A taint-tracking module for untrusted user input used in dangerous regular expression operations.
55+
*/
56+
module ReDoS = TaintTracking::Global<ReDoSConfig>;
57+
4058
/** A source of remote user input. */
4159
class RemoteSource extends Source instanceof RemoteFlowSource { }
4260

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2424
abstract class Sanitizer extends DataFlow::ExprNode { }
2525

2626
/**
27+
* DEPRECATED: Use `RegexInjection` instead.
28+
*
2729
* A taint-tracking configuration for untrusted user input used to construct regular expressions.
2830
*/
29-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
31+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3032
TaintTrackingConfiguration() { this = "RegexInjection" }
3133

3234
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -36,6 +38,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3638
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3739
}
3840

41+
/**
42+
* A taint-tracking configuration for untrusted user input used to construct regular expressions.
43+
*/
44+
private module RegexInjectionConfig implements DataFlow::ConfigSig {
45+
predicate isSource(DataFlow::Node source) { source instanceof Source }
46+
47+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
48+
49+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
50+
}
51+
52+
/**
53+
* A taint-tracking module for untrusted user input used to construct regular expressions.
54+
*/
55+
module RegexInjection = TaintTracking::Global<RegexInjectionConfig>;
56+
3957
/** A source of remote user input. */
4058
class RemoteSource extends Source instanceof RemoteFlowSource { }
4159

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2424
abstract class Sanitizer extends DataFlow::ExprNode { }
2525

2626
/**
27+
* DEPRECATED: Use `ResourceInjection` instead.
28+
*
2729
* A taint-tracking configuration for untrusted user input used in resource descriptors.
2830
*/
29-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
31+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3032
TaintTrackingConfiguration() { this = "ResourceInjection" }
3133

3234
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -36,6 +38,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3638
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3739
}
3840

41+
/**
42+
* A taint-tracking configuration for untrusted user input used in resource descriptors.
43+
*/
44+
private module ResourceInjectionConfig implements DataFlow::ConfigSig {
45+
predicate isSource(DataFlow::Node source) { source instanceof Source }
46+
47+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
48+
49+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
50+
}
51+
52+
/**
53+
* A taint-tracking module for untrusted user input used in resource descriptors.
54+
*/
55+
module ResourceInjection = TaintTracking::Global<ResourceInjectionConfig>;
56+
3957
/** A source of remote user input. */
4058
class RemoteSource extends Source instanceof RemoteFlowSource { }
4159

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { }
2525
abstract class Sanitizer extends DataFlow::ExprNode { }
2626

2727
/**
28+
* DEPRECATED: Use `SqlInjection` instead.
29+
*
2830
* A taint-tracking configuration for SQL injection vulnerabilities.
2931
*/
30-
class TaintTrackingConfiguration extends TaintTracking::Configuration {
32+
deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration {
3133
TaintTrackingConfiguration() { this = "SqlInjection" }
3234

3335
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,6 +39,32 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
3739
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
3840
}
3941

42+
/**
43+
* A taint-tracking configuration for SQL injection vulnerabilities.
44+
*/
45+
module SqlInjectionConfig implements DataFlow::ConfigSig {
46+
/**
47+
* Holds if `source` is a relevant data flow source.
48+
*/
49+
predicate isSource(DataFlow::Node source) { source instanceof Source }
50+
51+
/**
52+
* Holds if `sink` is a relevant data flow sink.
53+
*/
54+
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
55+
56+
/**
57+
* Holds if data flow through `node` is prohibited. This completely removes
58+
* `node` from the data flow graph.
59+
*/
60+
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
61+
}
62+
63+
/**
64+
* A taint-tracking module for SQL injection vulnerabilities.
65+
*/
66+
module SqlInjection = TaintTracking::Global<SqlInjectionConfig>;
67+
4068
/** A source of remote user input. */
4169
class RemoteSource extends Source instanceof RemoteFlowSource { }
4270

0 commit comments

Comments
 (0)