-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathRequestForgery.qll
More file actions
155 lines (137 loc) · 5.56 KB
/
Copy pathRequestForgery.qll
File metadata and controls
155 lines (137 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/** Provides classes to reason about server-side request forgery (SSRF) attacks. */
overlay[local?]
module;
import java
import semmle.code.java.frameworks.Networking
import semmle.code.java.frameworks.ApacheHttp
import semmle.code.java.frameworks.spring.Spring
import semmle.code.java.frameworks.JaxWS
import semmle.code.java.frameworks.javase.Http
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.Properties
private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.StringPrefixes
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.security.Sanitizers
/**
* A unit class for adding additional taint steps that are specific to server-side request forgery (SSRF) attacks.
*
* Extend this class to add additional taint steps to the SSRF query.
*/
class RequestForgeryAdditionalTaintStep extends Unit {
/**
* Holds if the step from `pred` to `succ` should be considered a taint
* step for server-side request forgery.
*/
abstract predicate propagatesTaint(DataFlow::Node pred, DataFlow::Node succ);
}
private class DefaultRequestForgeryAdditionalTaintStep extends RequestForgeryAdditionalTaintStep {
override predicate propagatesTaint(DataFlow::Node pred, DataFlow::Node succ) {
// propagate to a URI when its host is assigned to
exists(UriCreation c | c.getHostArg() = pred.asExpr() | succ.asExpr() = c)
or
// propagate to a URL when its host is assigned to
exists(UrlConstructorCall c | c.getHostArg() = pred.asExpr() | succ.asExpr() = c)
}
}
private class TypePropertiesRequestForgeryAdditionalTaintStep extends RequestForgeryAdditionalTaintStep
{
override predicate propagatesTaint(DataFlow::Node pred, DataFlow::Node succ) {
exists(MethodCall ma |
// Properties props = new Properties();
// props.setProperty("jdbcUrl", tainted);
// Propagate tainted value to the qualifier `props`
ma.getMethod() instanceof PropertiesSetPropertyMethod and
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "jdbcUrl" and
pred.asExpr() = ma.getArgument(1) and
succ.asExpr() = ma.getQualifier()
)
}
}
/** A data flow sink for server-side request forgery (SSRF) vulnerabilities. */
abstract class RequestForgerySink extends DataFlow::Node { }
private class DefaultRequestForgerySink extends RequestForgerySink {
DefaultRequestForgerySink() { sinkNode(this, "request-forgery") }
}
/** A sanitizer for request forgery vulnerabilities. */
abstract class RequestForgerySanitizer extends DataFlow::Node { }
private class PrimitiveSanitizer extends RequestForgerySanitizer instanceof SimpleTypeSanitizer { }
/**
* A string constant that contains a prefix which looks like when it is prepended to untrusted
* input, it will restrict the host or entity addressed.
*
* For example, anything containing `?` or `#`, or a slash that doesn't appear to be a protocol
* specifier (e.g. `http://` is not sanitizing), or specifically the string "/".
*/
class HostnameSanitizingPrefix extends InterestingPrefix {
int offset;
HostnameSanitizingPrefix() {
exists(this.getStringValue().regexpFind("([?#]|[^?#:/\\\\][/\\\\])|^/$", 0, offset))
}
override int getOffset() { result = offset }
}
/**
* A value that is the result of prepending a string that prevents any value from controlling the
* host of a URL.
*/
private class HostnameSanitizer extends RequestForgerySanitizer {
HostnameSanitizer() {
this.asExpr() = any(HostnameSanitizingPrefix hsp).getAnAppendedExpression()
}
}
/**
* An argument to a call to a `.contains()` method that is a sanitizer for URL redirects.
*
* Matches any method call where the method is named `contains`.
*/
private predicate isContainsUrlSanitizer(Guard guard, Expr e, boolean branch) {
guard =
any(MethodCall method |
method.getMethod().getName() = "contains" and
e = method.getArgument(0) and
branch = true
)
}
/**
* An URL argument to a call to `.contains()` that is a sanitizer for URL redirects.
*
* This `contains` method is usually called on a list, but the sanitizer matches any call to a method
* called `contains`, so other methods with the same name will also be considered sanitizers.
*/
private class ContainsUrlSanitizer extends RequestForgerySanitizer {
ContainsUrlSanitizer() {
this = DataFlow::BarrierGuard<isContainsUrlSanitizer/3>::getABarrierNode()
}
}
private class ExternalRequestForgerySanitizer extends RequestForgerySanitizer {
ExternalRequestForgerySanitizer() { barrierNode(this, "request-forgery") }
}
/**
* A comparison on the host of a url, that is a sanitizer for URL redirects.
* E.g. `"example.org".equals(url.getHost())"`
*/
private predicate isHostComparisonSanitizer(Guard guard, Expr e, boolean branch) {
guard =
any(MethodCall equalsCall |
equalsCall.getMethod().getName() = "equals" and
branch = true and
exists(MethodCall hostCall |
hostCall = [equalsCall.getQualifier(), equalsCall.getArgument(0)] and
hostCall.getMethod().hasQualifiedName("java.net", "URI", "getHost") and
e = hostCall.getQualifier()
)
)
}
/**
* A comparison on the `Host` property of a url, that is a sanitizer for URL redirects.
*/
private class HostComparisonSanitizer extends RequestForgerySanitizer {
HostComparisonSanitizer() {
this = DataFlow::BarrierGuard<isHostComparisonSanitizer/3>::getABarrierNode()
}
}
/**
* A comparison with a regular expression that is a sanitizer for URL redirects.
*/
private class RegexpCheckRequestForgerySanitizer extends RequestForgerySanitizer instanceof RegexpCheckBarrier
{ }