Skip to content

Commit 38826c9

Browse files
authored
Merge pull request github#12751 from egregius313/egregius313/dataflow-refactor-cleanup
Java: Finish dataflow refactor
2 parents ba982e2 + f106783 commit 38826c9

File tree

9 files changed

+117
-43
lines changed

9 files changed

+117
-43
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* The `sensitiveResultReceiver` predicate in `SensitiveResultReceiverQuery.qll` has been deprecated and replaced with `isSensitiveResultReceiver` in order to use the new dataflow API.

java/ql/lib/semmle/code/java/security/HardcodedCredentialsSourceCallQuery.qll

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import semmle.code.java.dataflow.DataFlow2
88
import HardcodedCredentials
99

1010
/**
11+
* DEPRECATED: Use `HardcodedCredentialSourceCallFlow` instead.
12+
*
1113
* A data-flow configuration that tracks hardcoded expressions flowing to a parameter whose name suggests
1214
* it may be a credential, excluding those which flow on to other such insecure usage sites.
1315
*/
14-
class HardcodedCredentialSourceCallConfiguration extends DataFlow::Configuration {
16+
deprecated class HardcodedCredentialSourceCallConfiguration extends DataFlow::Configuration {
1517
HardcodedCredentialSourceCallConfiguration() {
1618
this = "HardcodedCredentialSourceCallConfiguration"
1719
}
@@ -22,10 +24,28 @@ class HardcodedCredentialSourceCallConfiguration extends DataFlow::Configuration
2224
}
2325

2426
/**
27+
* A data-flow configuration that tracks hardcoded expressions flowing to a parameter whose name suggests
28+
* it may be a credential, excluding those which flow on to other such insecure usage sites.
29+
*/
30+
module HardcodedCredentialSourceCallConfig implements DataFlow::ConfigSig {
31+
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof HardcodedExpr }
32+
33+
predicate isSink(DataFlow::Node n) { n.asExpr() instanceof FinalCredentialsSourceSink }
34+
}
35+
36+
/**
37+
* Tracks hardcoded expressions flowing to a parameter whose name suggests
38+
* it may be a credential, excluding those which flow on to other such insecure usage sites.
39+
*/
40+
module HardcodedCredentialSourceCallFlow = DataFlow::Global<HardcodedCredentialSourceCallConfig>;
41+
42+
/**
43+
* DEPRECATED: Use `HardcodedCredentialParameterSourceCallFlow` instead.
44+
*
2545
* A data-flow configuration that tracks flow from an argument whose corresponding parameter name suggests
2646
* a credential, to an argument to a sensitive call.
2747
*/
28-
class HardcodedCredentialSourceCallConfiguration2 extends DataFlow2::Configuration {
48+
deprecated class HardcodedCredentialSourceCallConfiguration2 extends DataFlow2::Configuration {
2949
HardcodedCredentialSourceCallConfiguration2() {
3050
this = "HardcodedCredentialSourceCallConfiguration2"
3151
}
@@ -35,17 +55,33 @@ class HardcodedCredentialSourceCallConfiguration2 extends DataFlow2::Configurati
3555
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsSink }
3656
}
3757

58+
/**
59+
* A data-flow configuration that tracks flow from an argument whose corresponding parameter name suggests
60+
* a credential, to an argument to a sensitive call.
61+
*/
62+
module HardcodedCredentialParameterSourceCallConfig implements DataFlow::ConfigSig {
63+
predicate isSource(DataFlow::Node n) { n.asExpr() instanceof CredentialsSourceSink }
64+
65+
predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsSink }
66+
}
67+
68+
/**
69+
* Tracks flow from an argument whose corresponding parameter name suggests
70+
* a credential, to an argument to a sensitive call.
71+
*/
72+
module HardcodedCredentialParameterSourceCallFlow =
73+
DataFlow::Global<HardcodedCredentialParameterSourceCallConfig>;
74+
3875
/**
3976
* An argument to a call, where the parameter name corresponding
4077
* to the argument indicates that it may contain credentials, and
4178
* where this expression does not flow on to another `CredentialsSink`.
4279
*/
4380
class FinalCredentialsSourceSink extends CredentialsSourceSink {
4481
FinalCredentialsSourceSink() {
45-
not exists(HardcodedCredentialSourceCallConfiguration2 conf, CredentialsSink other |
46-
this != other
47-
|
48-
conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(other))
82+
not exists(CredentialsSink other | this != other |
83+
HardcodedCredentialParameterSourceCallFlow::flow(DataFlow::exprNode(this),
84+
DataFlow::exprNode(other))
4985
)
5086
}
5187
}

java/ql/lib/semmle/code/java/security/SensitiveResultReceiverQuery.qll

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** Definitions for the sensitive result receiver query. */
22

33
import java
4-
import semmle.code.java.dataflow.TaintTracking2
4+
import semmle.code.java.dataflow.TaintTracking
55
import semmle.code.java.dataflow.FlowSources
66
import semmle.code.java.security.SensitiveActions
77

@@ -17,21 +17,21 @@ private class ResultReceiverSendCall extends MethodAccess {
1717
Expr getSentData() { result = this.getArgument(1) }
1818
}
1919

20-
private class UntrustedResultReceiverConf extends TaintTracking2::Configuration {
21-
UntrustedResultReceiverConf() { this = "UntrustedResultReceiverConf" }
20+
private module UntrustedResultReceiverConfig implements DataFlow::ConfigSig {
21+
predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource }
2222

23-
override predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource }
24-
25-
override predicate isSink(DataFlow::Node node) {
23+
predicate isSink(DataFlow::Node node) {
2624
node.asExpr() = any(ResultReceiverSendCall c).getReceiver()
2725
}
2826
}
2927

28+
private module UntrustedResultReceiverFlow = TaintTracking::Global<UntrustedResultReceiverConfig>;
29+
3030
private predicate untrustedResultReceiverSend(DataFlow::Node src, ResultReceiverSendCall call) {
31-
any(UntrustedResultReceiverConf c).hasFlow(src, DataFlow::exprNode(call.getReceiver()))
31+
UntrustedResultReceiverFlow::flow(src, DataFlow::exprNode(call.getReceiver()))
3232
}
3333

34-
private class SensitiveResultReceiverConf extends TaintTracking::Configuration {
34+
deprecated private class SensitiveResultReceiverConf extends TaintTracking::Configuration {
3535
SensitiveResultReceiverConf() { this = "SensitiveResultReceiverConf" }
3636

3737
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
@@ -50,12 +50,46 @@ private class SensitiveResultReceiverConf extends TaintTracking::Configuration {
5050
}
5151
}
5252

53-
/** Holds if there is a path from sensitive data at `src` to a result receiver at `sink`, and the receiver was obtained from an untrusted source `recSrc`. */
54-
predicate sensitiveResultReceiver(
53+
private module SensitiveResultReceiverConfig implements DataFlow::ConfigSig {
54+
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof SensitiveExpr }
55+
56+
predicate isSink(DataFlow::Node node) {
57+
exists(ResultReceiverSendCall call |
58+
untrustedResultReceiverSend(_, call) and
59+
node.asExpr() = call.getSentData()
60+
)
61+
}
62+
63+
predicate allowImplicitRead(DataFlow::Node n, DataFlow::ContentSet c) { isSink(n) and exists(c) }
64+
}
65+
66+
/** Taint tracking flow for sensitive expressions flowing to untrusted result receivers. */
67+
module SensitiveResultReceiverFlow = TaintTracking::Global<SensitiveResultReceiverConfig>;
68+
69+
/**
70+
* DEPRECATED: Use `isSensitiveResultReceiver` instead.
71+
*
72+
* Holds if there is a path from sensitive data at `src` to a result receiver at `sink`, and the receiver was obtained from an untrusted source `recSrc`.
73+
*/
74+
deprecated predicate sensitiveResultReceiver(
5575
DataFlow::PathNode src, DataFlow::PathNode sink, DataFlow::Node recSrc
5676
) {
57-
exists(ResultReceiverSendCall call, SensitiveResultReceiverConf conf |
58-
conf.hasFlowPath(src, sink) and
77+
exists(ResultReceiverSendCall call |
78+
any(SensitiveResultReceiverConf c).hasFlowPath(src, sink) and
79+
sink.getNode().asExpr() = call.getSentData() and
80+
untrustedResultReceiverSend(recSrc, call)
81+
)
82+
}
83+
84+
/**
85+
* Holds if there is a path from sensitive data at `src` to a result receiver at `sink`, and the receiver was obtained from an untrusted source `recSrc`.
86+
*/
87+
predicate isSensitiveResultReceiver(
88+
SensitiveResultReceiverFlow::PathNode src, SensitiveResultReceiverFlow::PathNode sink,
89+
DataFlow::Node recSrc
90+
) {
91+
exists(ResultReceiverSendCall call |
92+
SensitiveResultReceiverFlow::flowPath(src, sink) and
5993
sink.getNode().asExpr() = call.getSentData() and
6094
untrustedResultReceiverSend(recSrc, call)
6195
)

java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsSourceCall.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212

1313
import java
1414
import semmle.code.java.security.HardcodedCredentialsSourceCallQuery
15-
import DataFlow::PathGraph
15+
import HardcodedCredentialSourceCallFlow::PathGraph
1616

1717
from
18-
DataFlow::PathNode source, DataFlow::PathNode sink,
19-
HardcodedCredentialSourceCallConfiguration conf
20-
where conf.hasFlowPath(source, sink)
18+
HardcodedCredentialSourceCallFlow::PathNode source,
19+
HardcodedCredentialSourceCallFlow::PathNode sink
20+
where HardcodedCredentialSourceCallFlow::flowPath(source, sink)
2121
select source.getNode(), source, sink, "Hard-coded value flows to $@.", sink.getNode(),
2222
"sensitive call"

java/ql/src/Security/CWE/CWE-927/SensitiveResultReceiver.ql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
import java
1515
import semmle.code.java.security.SensitiveResultReceiverQuery
16-
import DataFlow::PathGraph
16+
import SensitiveResultReceiverFlow::PathGraph
1717

18-
from DataFlow::PathNode src, DataFlow::PathNode sink, DataFlow::Node recSrc
19-
where sensitiveResultReceiver(src, sink, recSrc)
18+
from
19+
SensitiveResultReceiverFlow::PathNode src, SensitiveResultReceiverFlow::PathNode sink,
20+
DataFlow::Node recSrc
21+
where isSensitiveResultReceiver(src, sink, recSrc)
2022
select sink, src, sink, "This $@ is sent to a ResultReceiver obtained from $@.", src,
2123
"sensitive information", recSrc, "this untrusted source"

java/ql/test/library-tests/frameworks/ratpack/flow.ql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@ import semmle.code.java.dataflow.TaintTracking
33
import semmle.code.java.dataflow.FlowSources
44
import TestUtilities.InlineExpectationsTest
55

6-
class Conf extends TaintTracking::Configuration {
7-
Conf() { this = "qltest:frameworks:ratpack" }
8-
9-
override predicate isSource(DataFlow::Node n) {
6+
module Config implements DataFlow::ConfigSig {
7+
predicate isSource(DataFlow::Node n) {
108
n.asExpr().(MethodAccess).getMethod().hasName("taint")
119
or
1210
n instanceof RemoteFlowSource
1311
}
1412

15-
override predicate isSink(DataFlow::Node n) {
13+
predicate isSink(DataFlow::Node n) {
1614
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
1715
}
1816
}
1917

18+
module Flow = TaintTracking::Global<Config>;
19+
2020
class HasFlowTest extends InlineExpectationsTest {
2121
HasFlowTest() { this = "HasFlowTest" }
2222

2323
override string getARelevantTag() { result = "hasTaintFlow" }
2424

2525
override predicate hasActualResult(Location location, string element, string tag, string value) {
2626
tag = "hasTaintFlow" and
27-
exists(DataFlow::Node sink, Conf conf | conf.hasFlowTo(sink) |
27+
exists(DataFlow::Node sink | Flow::flowTo(sink) |
2828
sink.getLocation() = location and
2929
element = sink.toString() and
3030
value = ""
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import semmle.code.java.dataflow.FlowSources
22

3-
class Conf extends TaintTracking::Configuration {
4-
Conf() { this = "qltest:cwe-089:taintedString" }
3+
module Config implements DataFlow::ConfigSig {
4+
predicate isSource(DataFlow::Node source) { source instanceof UserInput }
55

6-
override predicate isSource(DataFlow::Node source) { source instanceof UserInput }
7-
8-
override predicate isSink(DataFlow::Node sink) { any() }
6+
predicate isSink(DataFlow::Node sink) { any() }
97
}
108

11-
from Conf conf, Expr tainted, Method method
9+
module Flow = TaintTracking::Global<Config>;
10+
11+
from Expr tainted, Method method
1212
where
13-
conf.hasFlowToExpr(tainted) and
13+
Flow::flowToExpr(tainted) and
1414
tainted.getEnclosingCallable() = method and
1515
tainted.getFile().getStem() = ["Test", "Validation"]
1616
select method, tainted.getLocation().getStartLine() - method.getLocation().getStartLine(), tainted

java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsSourceCall.ql

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ class HardcodedCredentialsSourceCallTest extends InlineExpectationsTest {
99

1010
override predicate hasActualResult(Location location, string element, string tag, string value) {
1111
tag = "HardcodedCredentialsSourceCall" and
12-
exists(DataFlow::Node sink, HardcodedCredentialSourceCallConfiguration conf |
13-
conf.hasFlow(_, sink)
14-
|
12+
exists(DataFlow::Node sink | HardcodedCredentialSourceCallFlow::flowTo(sink) |
1513
sink.getLocation() = location and
1614
element = sink.toString() and
1715
value = ""

java/ql/test/query-tests/security/CWE-927/SensitiveResultReceiver.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class ResultReceiverTest extends InlineExpectationsTest {
1414
override string getARelevantTag() { result = "hasSensitiveResultReceiver" }
1515

1616
override predicate hasActualResult(Location loc, string element, string tag, string value) {
17-
exists(DataFlow::PathNode sink |
18-
sensitiveResultReceiver(_, sink, _) and
17+
exists(SensitiveResultReceiverFlow::PathNode sink |
18+
isSensitiveResultReceiver(_, sink, _) and
1919
element = sink.toString() and
2020
loc = sink.getNode().getLocation() and
2121
tag = "hasSensitiveResultReceiver" and

0 commit comments

Comments
 (0)