Skip to content

Commit 7623432

Browse files
committed
Java: Remove/deprecate FlowStateString-based extension points.
1 parent 8ef4821 commit 7623432

File tree

7 files changed

+163
-84
lines changed

7 files changed

+163
-84
lines changed

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

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,44 @@ private import semmle.code.java.dataflow.TaintTracking
66
private import semmle.code.java.frameworks.android.Intent
77
private import semmle.code.java.frameworks.android.PendingIntent
88

9+
private newtype TPendingIntentState =
10+
TMutablePendingIntent() or
11+
TNoState()
12+
13+
/** A flow state for an implicit `PendingIntent` flow. */
14+
class PendingIntentState extends TPendingIntentState {
15+
/** Gets a textual representation of this element. */
16+
abstract string toString();
17+
}
18+
19+
/** A flow state indicating that a mutable `PendingIntent` has been created. */
20+
class MutablePendingIntent extends PendingIntentState, TMutablePendingIntent {
21+
override string toString() { result = "MutablePendingIntent" }
22+
}
23+
24+
/** The initial flow state for an implicit `PendingIntent` flow. */
25+
class NoState extends PendingIntentState, TNoState {
26+
override string toString() { result = "NoState" }
27+
}
28+
929
/** A source for an implicit `PendingIntent` flow. */
1030
abstract class ImplicitPendingIntentSource extends DataFlow::Node {
11-
/** Holds if this source has the specified `state`. */
12-
predicate hasState(DataFlow::FlowState state) { state = "" }
31+
/**
32+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
33+
*
34+
* Holds if this source has the specified `state`.
35+
*/
36+
deprecated predicate hasState(DataFlow::FlowState state) { state = "" }
1337
}
1438

1539
/** A sink that sends an implicit and mutable `PendingIntent` to a third party. */
1640
abstract class ImplicitPendingIntentSink extends DataFlow::Node {
17-
/** Holds if this sink has the specified `state`. */
18-
predicate hasState(DataFlow::FlowState state) { state = "" }
41+
/**
42+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
43+
*
44+
* Holds if this sink has the specified `state`.
45+
*/
46+
deprecated predicate hasState(DataFlow::FlowState state) { state = "" }
1947
}
2048

2149
/**
@@ -32,11 +60,19 @@ class ImplicitPendingIntentAdditionalTaintStep extends Unit {
3260
predicate step(DataFlow::Node node1, DataFlow::Node node2) { none() }
3361

3462
/**
63+
* Holds if the step from `node1` to `node2` creates a mutable `PendingIntent`.
64+
*/
65+
predicate mutablePendingIntentCreation(DataFlow::Node node1, DataFlow::Node node2) { none() }
66+
67+
/**
68+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
69+
* Use `mutablePendingIntentCreation` instead.
70+
*
3571
* Holds if the step from `node1` to `node2` should be considered a taint
3672
* step for flows related to the use of implicit `PendingIntent`s. This step is only applicable
3773
* in `state1` and updates the flow state to `state2`.
3874
*/
39-
predicate step(
75+
deprecated predicate step(
4076
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
4177
DataFlow::FlowState state2
4278
) {
@@ -66,17 +102,10 @@ private class SendPendingIntent extends ImplicitPendingIntentSink {
66102
or
67103
sinkNode(this, "pending-intents")
68104
}
69-
70-
override predicate hasState(DataFlow::FlowState state) { state = "MutablePendingIntent" }
71105
}
72106

73107
private class MutablePendingIntentFlowStep extends ImplicitPendingIntentAdditionalTaintStep {
74-
override predicate step(
75-
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
76-
DataFlow::FlowState state2
77-
) {
78-
state1 = "" and
79-
state2 = "MutablePendingIntent" and
108+
override predicate mutablePendingIntentCreation(DataFlow::Node node1, DataFlow::Node node2) {
80109
exists(PendingIntentCreation pic, Argument flagArg |
81110
node1.asExpr() = pic.getIntentArg() and
82111
node2.asExpr() = pic and

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ deprecated class ImplicitPendingIntentStartConf extends TaintTracking::Configura
6060
* being wrapped in another implicit `Intent` that gets started.
6161
*/
6262
module ImplicitPendingIntentStartConfig implements DataFlow::StateConfigSig {
63-
class FlowState = DataFlow::FlowState;
63+
class FlowState = PendingIntentState;
6464

6565
predicate isSource(DataFlow::Node source, FlowState state) {
66-
source.(ImplicitPendingIntentSource).hasState(state)
66+
source instanceof ImplicitPendingIntentSource and state instanceof NoState
6767
}
6868

6969
predicate isSink(DataFlow::Node sink, FlowState state) {
70-
sink.(ImplicitPendingIntentSink).hasState(state)
70+
sink instanceof ImplicitPendingIntentSink and state instanceof MutablePendingIntent
7171
}
7272

7373
predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof ExplicitIntentSanitizer }
@@ -79,7 +79,9 @@ module ImplicitPendingIntentStartConfig implements DataFlow::StateConfigSig {
7979
predicate isAdditionalFlowStep(
8080
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
8181
) {
82-
any(ImplicitPendingIntentAdditionalTaintStep c).step(node1, state1, node2, state2)
82+
any(ImplicitPendingIntentAdditionalTaintStep c).mutablePendingIntentCreation(node1, node2) and
83+
state1 instanceof NoState and
84+
state2 instanceof MutablePendingIntent
8385
}
8486

8587
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {

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

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,76 @@
33
private import semmle.code.java.security.Encryption
44
private import semmle.code.java.dataflow.DataFlow
55
private import semmle.code.java.security.internal.EncryptionKeySizes
6+
import codeql.util.Either
7+
8+
/** A minimum recommended key size for some algorithm. */
9+
abstract class MinimumKeySize extends int {
10+
bindingset[this]
11+
MinimumKeySize() { any() }
12+
13+
/** Gets a textual representation of this element. */
14+
string toString() { result = super.toString() }
15+
}
16+
17+
/**
18+
* A class of algorithms for which a key size smaller than the recommended key
19+
* size might be embedded in the algorithm name.
20+
*/
21+
abstract class AlgorithmKind extends string {
22+
bindingset[this]
23+
AlgorithmKind() { any() }
24+
25+
/** Gets a textual representation of this element. */
26+
string toString() { result = super.toString() }
27+
}
28+
29+
/**
30+
* A key size that is greater than the tracked value and equal to the minimum
31+
* recommended key size for some algorithm, or a kind of algorithm for which the
32+
* tracked string indicates a too small key size.
33+
*/
34+
final class KeySizeState = Either<MinimumKeySize, AlgorithmKind>::Either;
635

736
/** A source for an insufficient key size. */
837
abstract class InsufficientKeySizeSource extends DataFlow::Node {
938
/** Holds if this source has the specified `state`. */
10-
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
39+
abstract predicate hasState(KeySizeState state);
1140
}
1241

1342
/** A sink for an insufficient key size. */
1443
abstract class InsufficientKeySizeSink extends DataFlow::Node {
15-
/** Holds if this sink has the specified `state`. */
16-
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
44+
/** Holds if this sink accepts the specified `state`. */
45+
final predicate hasState(KeySizeState state) {
46+
state.asLeft() <= this.minimumKeySize() or this.algorithmKind(state.asRight())
47+
}
48+
49+
/** Gets the minimum recommended key size. */
50+
abstract int minimumKeySize();
51+
52+
/**
53+
* Holds if this sink recommends a keysize that is greater than the value in a
54+
* source with the given algorithm kind.
55+
*/
56+
predicate algorithmKind(AlgorithmKind kind) { none() }
57+
}
58+
59+
/** A source for an insufficient key size used in some algorithm. */
60+
private class IntegerLiteralSource extends InsufficientKeySizeSource {
61+
private int value;
62+
63+
IntegerLiteralSource() { this.asExpr().(IntegerLiteral).getIntValue() = value }
64+
65+
override predicate hasState(KeySizeState state) {
66+
state.asLeft() = min(MinimumKeySize m | value < m)
67+
}
1768
}
1869

1970
/** Provides models for asymmetric cryptography. */
2071
private module Asymmetric {
2172
/** Provides models for non-elliptic-curve asymmetric cryptography. */
2273
private module NonEllipticCurve {
23-
/** A source for an insufficient key size used in RSA, DSA, and DH algorithms. */
24-
private class Source extends InsufficientKeySizeSource {
25-
string algoName;
26-
27-
Source() { this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize(algoName) }
28-
29-
override predicate hasState(DataFlow::FlowState state) {
30-
state = getMinKeySize(algoName).toString()
31-
}
74+
private class NonEllipticCurveKeySize extends MinimumKeySize {
75+
NonEllipticCurveKeySize() { this = getMinKeySize(_) }
3276
}
3377

3478
/** A sink for an insufficient key size used in RSA, DSA, and DH algorithms. */
@@ -46,9 +90,7 @@ private module Asymmetric {
4690
exists(Spec spec | this.asExpr() = spec.getKeySizeArg() and algoName = spec.getAlgoName())
4791
}
4892

49-
override predicate hasState(DataFlow::FlowState state) {
50-
state = getMinKeySize(algoName).toString()
51-
}
93+
override int minimumKeySize() { result = getMinKeySize(algoName) }
5294
}
5395

5496
/** Returns the minimum recommended key size for RSA, DSA, and DH algorithms. */
@@ -88,16 +130,24 @@ private module Asymmetric {
88130

89131
/** Provides models for elliptic-curve asymmetric cryptography. */
90132
private module EllipticCurve {
133+
private class EllipticCurveKeySize extends MinimumKeySize {
134+
EllipticCurveKeySize() { this = getMinKeySize() }
135+
}
136+
137+
private class EllipticCurveKind extends AlgorithmKind {
138+
EllipticCurveKind() { this = "EC" }
139+
}
140+
91141
/** A source for an insufficient key size used in elliptic curve (EC) algorithms. */
92142
private class Source extends InsufficientKeySizeSource {
93143
Source() {
94-
this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize()
95-
or
96144
// the below is needed for cases when the key size is embedded in the curve name
97145
getKeySize(this.asExpr().(StringLiteral).getValue()) < getMinKeySize()
98146
}
99147

100-
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
148+
override predicate hasState(KeySizeState state) {
149+
state.asRight() instanceof EllipticCurveKind
150+
}
101151
}
102152

103153
/** A sink for an insufficient key size used in elliptic curve (EC) algorithms. */
@@ -112,7 +162,9 @@ private module Asymmetric {
112162
exists(Spec s | this.asExpr() = s.getKeySizeArg())
113163
}
114164

115-
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
165+
override int minimumKeySize() { result = getMinKeySize() }
166+
167+
override predicate algorithmKind(AlgorithmKind kind) { kind instanceof EllipticCurveKind }
116168
}
117169

118170
/** Returns the minimum recommended key size for elliptic curve (EC) algorithms. */
@@ -176,11 +228,8 @@ private module Asymmetric {
176228

177229
/** Provides models for symmetric cryptography. */
178230
private module Symmetric {
179-
/** A source for an insufficient key size used in AES algorithms. */
180-
private class Source extends InsufficientKeySizeSource {
181-
Source() { this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize() }
182-
183-
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
231+
private class SymmetricKeySize extends MinimumKeySize {
232+
SymmetricKeySize() { this = getMinKeySize() }
184233
}
185234

186235
/** A sink for an insufficient key size used in AES algorithms. */
@@ -193,7 +242,7 @@ private module Symmetric {
193242
)
194243
}
195244

196-
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
245+
override int minimumKeySize() { result = getMinKeySize() }
197246
}
198247

199248
/** Returns the minimum recommended key size for AES algorithms. */

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

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,27 @@ deprecated class KeySizeConfiguration extends DataFlow::Configuration {
1212
KeySizeConfiguration() { this = "KeySizeConfiguration" }
1313

1414
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
15-
source.(InsufficientKeySizeSource).hasState(state)
15+
exists(KeySizeState s | source.(InsufficientKeySizeSource).hasState(s) and state = s.toString())
1616
}
1717

1818
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
19-
sink.(InsufficientKeySizeSink).hasState(state)
19+
exists(KeySizeState s | sink.(InsufficientKeySizeSink).hasState(s) and state = s.toString())
2020
}
2121
}
2222

2323
/**
2424
* A data flow configuration for tracking key sizes used in cryptographic algorithms.
2525
*/
2626
module KeySizeConfig implements DataFlow::StateConfigSig {
27-
class FlowState = DataFlow::FlowState;
27+
class FlowState = KeySizeState;
2828

29-
predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
29+
predicate isSource(DataFlow::Node source, KeySizeState state) {
3030
source.(InsufficientKeySizeSource).hasState(state)
3131
}
3232

33-
predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
33+
predicate isSink(DataFlow::Node sink, KeySizeState state) {
3434
sink.(InsufficientKeySizeSink).hasState(state)
3535
}
36-
37-
predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() }
38-
39-
predicate isAdditionalFlowStep(
40-
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
41-
DataFlow::FlowState state2
42-
) {
43-
none()
44-
}
4536
}
4637

4738
/** Tracks key sizes used in cryptographic algorithms. */

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

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,28 @@ private import semmle.code.java.dataflow.TaintTracking
99
* A source for server-side template injection (SST) vulnerabilities.
1010
*/
1111
abstract class TemplateInjectionSource extends DataFlow::Node {
12-
/** Holds if this source has the specified `state`. */
13-
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
12+
/**
13+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
14+
*
15+
* Holds if this source has the specified `state`.
16+
*/
17+
deprecated predicate hasState(DataFlow::FlowState state) {
18+
state instanceof DataFlow::FlowStateEmpty
19+
}
1420
}
1521

1622
/**
1723
* A sink for server-side template injection (SST) vulnerabilities.
1824
*/
1925
abstract class TemplateInjectionSink extends DataFlow::Node {
20-
/** Holds if this sink has the specified `state`. */
21-
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
26+
/**
27+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
28+
*
29+
* Holds if this sink has the specified `state`.
30+
*/
31+
deprecated predicate hasState(DataFlow::FlowState state) {
32+
state instanceof DataFlow::FlowStateEmpty
33+
}
2234
}
2335

2436
/**
@@ -35,11 +47,13 @@ class TemplateInjectionAdditionalTaintStep extends Unit {
3547
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
3648

3749
/**
50+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
51+
*
3852
* Holds if the step from `node1` to `node2` should be considered a taint
3953
* step for flows related toserver-side template injection (SST) vulnerabilities.
4054
* This step is only applicable in `state1` and updates the flow state to `state2`.
4155
*/
42-
predicate isAdditionalTaintStep(
56+
deprecated predicate isAdditionalTaintStep(
4357
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
4458
DataFlow::FlowState state2
4559
) {
@@ -53,13 +67,19 @@ class TemplateInjectionAdditionalTaintStep extends Unit {
5367
abstract class TemplateInjectionSanitizer extends DataFlow::Node { }
5468

5569
/**
70+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
71+
*
5672
* A sanitizer for server-side template injection (SST) vulnerabilities.
5773
* This sanitizer is only applicable when `TemplateInjectionSanitizerWithState::hasState`
5874
* holds for the flow state.
5975
*/
60-
abstract class TemplateInjectionSanitizerWithState extends DataFlow::Node {
61-
/** Holds if this sanitizer has the specified `state`. */
62-
abstract predicate hasState(DataFlow::FlowState state);
76+
abstract deprecated class TemplateInjectionSanitizerWithState extends DataFlow::Node {
77+
/**
78+
* DEPRECATED: Open-ended flow state is not intended to be part of the extension points.
79+
*
80+
* Holds if this sanitizer has the specified `state`.
81+
*/
82+
abstract deprecated predicate hasState(DataFlow::FlowState state);
6383
}
6484

6585
private class DefaultTemplateInjectionSource extends TemplateInjectionSource instanceof ThreatModelFlowSource

0 commit comments

Comments
 (0)