Skip to content

Commit 6fcaae2

Browse files
committed
Add tests and fix bugs highlighted by them
1 parent f19eb78 commit 6fcaae2

File tree

6 files changed

+514
-12
lines changed

6 files changed

+514
-12
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ private class FileSummaryModels extends SummaryModelCsv {
8282
"java.io;File;true;getCanonicalFile;;;Argument[-1];ReturnValue;taint;manual",
8383
"java.io;File;true;getCanonicalPath;;;Argument[-1];ReturnValue;taint;manual",
8484
"java.io;File;true;toPath;;;Argument[-1];ReturnValue;taint;manual",
85+
"java.io;File;true;toString;;;Argument[-1];ReturnValue;taint;manual",
8586
"java.io;File;true;toURI;;;Argument[-1];ReturnValue;taint;manual",
8687
"java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint;manual",
8788
"java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint;manual",

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

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ private class ExactPathMatchSanitizer extends PathInjectionSanitizer {
7272
private class AllowListGuard extends Guard instanceof MethodAccess {
7373
AllowListGuard() {
7474
(isStringPrefixMatch(this) or isPathPrefixMatch(this)) and
75-
not isDisallowedPrefix(super.getAnArgument())
75+
not isDisallowedPrefix(super.getAnArgument()) and
76+
not isDisallowedWord(super.getAnArgument())
7677
}
7778

7879
Expr getCheckedExpr() { result = super.getQualifier() }
@@ -86,11 +87,13 @@ private class AllowListGuard extends Guard instanceof MethodAccess {
8687
private predicate allowListGuard(Guard g, Expr e, boolean branch) {
8788
branch = true and
8889
TaintTracking::localExprTaint(e, g.(AllowListGuard).getCheckedExpr()) and
89-
exists(MethodAccess previousGuard |
90+
exists(Expr previousGuard |
9091
TaintTracking::localExprTaint(previousGuard.(PathNormalizeSanitizer),
9192
g.(AllowListGuard).getCheckedExpr())
9293
or
93-
previousGuard.(PathTraversalGuard).controls(g.getBasicBlock().(ConditionBlock), false)
94+
previousGuard
95+
.(PathTraversalGuard)
96+
.controls(g.getBasicBlock().(ConditionBlock), previousGuard.(PathTraversalGuard).getBranch())
9497
)
9598
}
9699

@@ -106,9 +109,9 @@ private class AllowListSanitizer extends PathInjectionSanitizer {
106109
* been checked for a trusted prefix.
107110
*/
108111
private predicate dotDotCheckGuard(Guard g, Expr e, boolean branch) {
109-
branch = false and
112+
branch = g.(PathTraversalGuard).getBranch() and
110113
TaintTracking::localExprTaint(e, g.(PathTraversalGuard).getCheckedExpr()) and
111-
exists(MethodAccess previousGuard |
114+
exists(Guard previousGuard |
112115
previousGuard.(AllowListGuard).controls(g.getBasicBlock().(ConditionBlock), true)
113116
or
114117
previousGuard.(BlockListGuard).controls(g.getBasicBlock().(ConditionBlock), false)
@@ -142,11 +145,13 @@ private class BlockListGuard extends Guard instanceof MethodAccess {
142145
private predicate blockListGuard(Guard g, Expr e, boolean branch) {
143146
branch = false and
144147
TaintTracking::localExprTaint(e, g.(BlockListGuard).getCheckedExpr()) and
145-
exists(MethodAccess previousGuard |
148+
exists(Expr previousGuard |
146149
TaintTracking::localExprTaint(previousGuard.(PathNormalizeSanitizer),
147150
g.(BlockListGuard).getCheckedExpr())
148151
or
149-
previousGuard.(PathTraversalGuard).controls(g.getBasicBlock().(ConditionBlock), false)
152+
previousGuard
153+
.(PathTraversalGuard)
154+
.controls(g.getBasicBlock().(ConditionBlock), previousGuard.(PathTraversalGuard).getBranch())
150155
)
151156
}
152157

@@ -200,14 +205,35 @@ private predicate isDisallowedWord(CompileTimeConstantExpr word) {
200205
}
201206

202207
/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
203-
private class PathTraversalGuard extends Guard instanceof MethodAccess {
208+
private class PathTraversalGuard extends Guard {
204209
PathTraversalGuard() {
205-
super.getMethod().getDeclaringType() instanceof TypeString and
206-
super.getMethod().hasName(["contains", "indexOf"]) and
207-
super.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
210+
exists(MethodAccess ma |
211+
ma.getMethod().getDeclaringType() instanceof TypeString and
212+
ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
213+
|
214+
this = ma and
215+
ma.getMethod().hasName("contains")
216+
or
217+
exists(EqualityTest eq |
218+
this = eq and
219+
ma.getMethod().hasName(["indexOf", "lastIndexOf"]) and
220+
eq.getAnOperand() = ma and
221+
eq.getAnOperand().(CompileTimeConstantExpr).getIntValue() = -1
222+
)
223+
)
208224
}
209225

210-
Expr getCheckedExpr() { result = super.getQualifier() }
226+
Expr getCheckedExpr() {
227+
exists(MethodAccess ma | ma = this.(BinaryExpr).getAnOperand() or ma = this |
228+
result = ma.getQualifier()
229+
)
230+
}
231+
232+
boolean getBranch() {
233+
this instanceof MethodAccess and result = false
234+
or
235+
result = this.(EqualityTest).polarity()
236+
}
211237
}
212238

213239
/** A complementary sanitizer that protects against path traversal using path normalization. */

0 commit comments

Comments
 (0)