Skip to content

Commit 08c67fb

Browse files
committed
Use PathInjectionSanitizer in relevant queries
1 parent dff878e commit 08c67fb

File tree

4 files changed

+24
-53
lines changed

4 files changed

+24
-53
lines changed

java/ql/src/Security/CWE/CWE-022/TaintedPath.ql

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,26 @@ import java
1717
import semmle.code.java.dataflow.FlowSources
1818
private import semmle.code.java.dataflow.ExternalFlow
1919
import semmle.code.java.security.PathCreation
20+
import semmle.code.java.security.PathSanitizer
2021
import DataFlow::PathGraph
2122
import TaintedPathCommon
2223

23-
predicate containsDotDotSanitizer(Guard g, Expr e, boolean branch) {
24-
exists(MethodAccess contains | g = contains |
25-
contains.getMethod().hasName("contains") and
26-
contains.getAnArgument().(StringLiteral).getValue() = ".." and
27-
e = contains.getQualifier() and
28-
branch = false
29-
)
30-
}
31-
3224
class TaintedPathConfig extends TaintTracking::Configuration {
3325
TaintedPathConfig() { this = "TaintedPathConfig" }
3426

3527
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
3628

3729
override predicate isSink(DataFlow::Node sink) {
38-
(
39-
sink.asExpr() = any(PathCreation p).getAnInput()
40-
or
41-
sinkNode(sink, "create-file")
42-
) and
43-
not guarded(sink.asExpr())
30+
sink.asExpr() = any(PathCreation p).getAnInput()
31+
or
32+
sinkNode(sink, "create-file")
4433
}
4534

46-
override predicate isSanitizer(DataFlow::Node node) {
47-
exists(Type t | t = node.getType() | t instanceof BoxedType or t instanceof PrimitiveType)
48-
or
49-
node = DataFlow::BarrierGuard<containsDotDotSanitizer/3>::getABarrierNode()
35+
override predicate isSanitizer(DataFlow::Node sanitizer) {
36+
sanitizer.getType() instanceof BoxedType or
37+
sanitizer.getType() instanceof PrimitiveType or
38+
sanitizer.getType() instanceof NumberType or
39+
sanitizer instanceof PathInjectionSanitizer
5040
}
5141

5242
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {

java/ql/src/Security/CWE/CWE-022/TaintedPathCommon.qll

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
*/
44

55
import java
6-
import semmle.code.java.controlflow.Guards
7-
import semmle.code.java.security.PathCreation
86
import semmle.code.java.frameworks.Networking
97
import semmle.code.java.dataflow.DataFlow
108

@@ -48,29 +46,3 @@ private class TaintPreservingUriCtorParam extends Parameter {
4846
)
4947
}
5048
}
51-
52-
private predicate inWeakCheck(Expr e) {
53-
// None of these are sufficient to guarantee that a string is safe.
54-
exists(MethodAccess m, Method def | m.getQualifier() = e and m.getMethod() = def |
55-
def.getName() = "startsWith" or
56-
def.getName() = "endsWith" or
57-
def.getName() = "isEmpty" or
58-
def.getName() = "equals"
59-
)
60-
or
61-
// Checking against `null` has no bearing on path traversal.
62-
exists(EqualityTest b | b.getAnOperand() = e | b.getAnOperand() instanceof NullLiteral)
63-
}
64-
65-
// Ignore cases where the variable has been checked somehow,
66-
// but allow some particularly obviously bad cases.
67-
predicate guarded(VarAccess e) {
68-
exists(PathCreation p | e = p.getAnInput()) and
69-
exists(ConditionBlock cb, Expr c |
70-
cb.getCondition().getAChildExpr*() = c and
71-
c = e.getVariable().getAnAccess() and
72-
cb.controls(e.getBasicBlock(), true) and
73-
// Disallow a few obviously bad checks.
74-
not inWeakCheck(c)
75-
)
76-
}

java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import java
1717
import semmle.code.java.dataflow.FlowSources
1818
private import semmle.code.java.dataflow.ExternalFlow
1919
import semmle.code.java.security.PathCreation
20+
import semmle.code.java.security.PathSanitizer
2021
import DataFlow::PathGraph
2122
import TaintedPathCommon
2223

@@ -26,12 +27,16 @@ class TaintedPathLocalConfig extends TaintTracking::Configuration {
2627
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
2728

2829
override predicate isSink(DataFlow::Node sink) {
29-
(
30-
sink.asExpr() = any(PathCreation p).getAnInput()
31-
or
32-
sinkNode(sink, "create-file")
33-
) and
34-
not guarded(sink.asExpr())
30+
sink.asExpr() = any(PathCreation p).getAnInput()
31+
or
32+
sinkNode(sink, "create-file")
33+
}
34+
35+
override predicate isSanitizer(DataFlow::Node sanitizer) {
36+
sanitizer.getType() instanceof BoxedType or
37+
sanitizer.getType() instanceof PrimitiveType or
38+
sanitizer.getType() instanceof NumberType or
39+
sanitizer instanceof PathInjectionSanitizer
3540
}
3641

3742
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {

java/ql/src/Security/CWE/CWE-022/ZipSlip.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import java
1616
import semmle.code.java.controlflow.Guards
1717
import semmle.code.java.dataflow.SSA
1818
import semmle.code.java.dataflow.TaintTracking
19+
import semmle.code.java.security.PathSanitizer
1920
import DataFlow
2021
import PathGraph
2122
private import semmle.code.java.dataflow.ExternalFlow
@@ -132,6 +133,7 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
132133
}
133134

134135
override predicate isSanitizer(Node node) {
136+
// TODO: Merge this sanitizers into PathInjectionSanitizer
135137
exists(Guard g, SsaVariable var, RValue varuse | validateFilePath(var, g) |
136138
varuse = node.asExpr() and
137139
varuse = var.getAUse() and
@@ -144,6 +146,8 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
144146
adjacentUseUseSameVar(rv, node.asExpr()) and
145147
ma.getBasicBlock().bbDominates(node.asExpr().getBasicBlock())
146148
)
149+
or
150+
node instanceof PathInjectionSanitizer
147151
}
148152
}
149153

0 commit comments

Comments
 (0)