Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 4c9bf22

Browse files
author
Sauyon Lee
committed
OpenRedirect: treat assignments to Url.Path as a barrier
1 parent 8cc60ba commit 4c9bf22

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

ql/src/semmle/go/security/OpenUrlRedirectCustomizations.qll

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,41 @@ module OpenUrlRedirect {
5050
}
5151
}
5252

53+
/**
54+
* Holds if `a` and `b` read the same variable, field, or method.
55+
*/
56+
predicate readsSameEntity(Read a, Read b) {
57+
exists(DataFlow::Node aBase, DataFlow::Node bBase | readsSameEntity(aBase, bBase) |
58+
exists(Field f | a.readsField(aBase, f) | b.readsField(bBase, f))
59+
or
60+
exists(Method m | a.readsMethod(aBase, m) | b.readsMethod(bBase, m))
61+
)
62+
}
63+
64+
/**
65+
* An access to a variable that is preceded by an assignment to its `Path` field.
66+
*
67+
* This is overapproximate; this will currently remove flow through all `Url.Path` assignments
68+
* which contain a substring that could sanitize data.
69+
*/
70+
class PathAssignmentBarrier extends Barrier, Read {
71+
PathAssignmentBarrier() {
72+
exists(Write w, Field f, Read writeBase, ValueEntity v |
73+
f.getName() = "Path" and
74+
hasHostnameSanitizingSubstring(w.getRhs()) and
75+
readsSameEntity(this, writeBase)
76+
|
77+
w.writesField(writeBase, f, _) and
78+
w.getBasicBlock().(ReachableBasicBlock).dominates(this.asInstruction().getBasicBlock()) and
79+
(
80+
not w.getBasicBlock() = this.asInstruction().getBasicBlock()
81+
or
82+
w.getASuccessor+() = this.asInstruction()
83+
)
84+
)
85+
}
86+
}
87+
5388
/**
5489
* A call to a function called `isLocalUrl` or similar, which is
5590
* considered a barrier for purposes of URL redirection.

ql/src/semmle/go/security/UrlConcatenation.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ predicate sanitizingPrefixEdge(DataFlow::Node source, DataFlow::Node sink) {
5555
* In the latter two cases, the additional check is necessary to avoid a `/` that could be interpreted as
5656
* the `//` separating the (optional) scheme from the hostname.
5757
*/
58-
private predicate hasHostnameSanitizingSubstring(DataFlow::Node nd) {
58+
predicate hasHostnameSanitizingSubstring(DataFlow::Node nd) {
5959
nd.getStringValue().regexpMatch(".*([?#]|[^?#:/\\\\][/\\\\]).*|[/\\\\][^/\\\\].*")
6060
or
6161
hasHostnameSanitizingSubstring(StringConcatenation::getAnOperand(nd))

0 commit comments

Comments
 (0)