Skip to content

Commit 2cada38

Browse files
committed
Refactored into InsecureBasicAuth.qll
1 parent 905be67 commit 2cada38

File tree

3 files changed

+273
-216
lines changed

3 files changed

+273
-216
lines changed

java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql

Lines changed: 5 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -14,225 +14,23 @@
1414
*/
1515

1616
import java
17-
import semmle.code.java.frameworks.Networking
18-
import semmle.code.java.frameworks.ApacheHttp
1917
import semmle.code.java.dataflow.TaintTracking
18+
import semmle.code.java.security.InsecureBasicAuth
2019
import DataFlow::PathGraph
2120

22-
/**
23-
* Class of Java URL constructor.
24-
*/
25-
class URLConstructor extends ClassInstanceExpr {
26-
URLConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl }
27-
28-
predicate hasHttpStringArg() {
29-
this.getConstructor().getParameter(0).getType() instanceof TypeString and
30-
(
31-
// URLs constructed with any of the three string constructors below:
32-
// `URL(String protocol, String host, int port, String file)`,
33-
// `URL(String protocol, String host, int port, String file, URLStreamHandler handler)`,
34-
// `URL(String protocol, String host, String file)`
35-
this.getConstructor().getNumberOfParameters() > 1 and
36-
concatHttpString(getArgument(0), this.getArgument(1)) // First argument contains the protocol part and the second argument contains the host part.
37-
or
38-
// URLs constructed with the string constructor `URL(String spec)`
39-
this.getConstructor().getNumberOfParameters() = 1 and
40-
this.getArgument(0) instanceof HttpString // First argument contains the whole spec.
41-
)
42-
}
43-
}
44-
45-
/**
46-
* Class of Java URI constructor.
47-
*/
48-
class URIConstructor extends ClassInstanceExpr {
49-
URIConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUri }
50-
51-
predicate hasHttpStringArg() {
52-
(
53-
this.getNumArgument() = 1 and
54-
this.getArgument(0) instanceof HttpString // `URI(String str)`
55-
or
56-
this.getNumArgument() = 4 and
57-
concatHttpString(this.getArgument(0), this.getArgument(1)) // `URI(String scheme, String host, String path, String fragment)`
58-
or
59-
this.getNumArgument() = 5 and
60-
concatHttpString(this.getArgument(0), this.getArgument(1)) // `URI(String scheme, String authority, String path, String query, String fragment)` without user-info in authority
61-
or
62-
this.getNumArgument() = 7 and
63-
concatHttpString(this.getArgument(0), this.getArgument(2)) // `URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)`
64-
)
65-
}
66-
}
67-
68-
/**
69-
* String of HTTP URLs not in private domains.
70-
*/
71-
class HttpStringLiteral extends StringLiteral {
72-
HttpStringLiteral() {
73-
// Match URLs with the HTTP protocol and without private IP addresses to reduce false positives.
74-
exists(string s | this.getRepresentedString() = s |
75-
s.regexpMatch("(?i)http://[\\[a-zA-Z0-9].*") and
76-
not s.substring(7, s.length()) instanceof PrivateHostName
77-
)
78-
}
79-
}
80-
81-
/**
82-
* Checks both parts of protocol and host.
83-
*/
84-
predicate concatHttpString(Expr protocol, Expr host) {
85-
(
86-
protocol.(CompileTimeConstantExpr).getStringValue().regexpMatch("(?i)http(://)?") or
87-
protocol
88-
.(VarAccess)
89-
.getVariable()
90-
.getAnAssignedValue()
91-
.(CompileTimeConstantExpr)
92-
.getStringValue()
93-
.regexpMatch("(?i)http(://)?")
94-
) and
95-
not exists(string hostString |
96-
hostString = host.(CompileTimeConstantExpr).getStringValue() or
97-
hostString =
98-
host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
99-
|
100-
hostString.length() = 0 or // Empty host is loopback address
101-
hostString instanceof PrivateHostName
102-
)
103-
}
104-
105-
/** Gets the leftmost operand in a concatenated string */
106-
Expr getLeftmostConcatOperand(Expr expr) {
107-
if expr instanceof AddExpr
108-
then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand())
109-
else result = expr
110-
}
111-
112-
/**
113-
* String concatenated with `HttpStringLiteral`.
114-
*/
115-
class HttpString extends Expr {
116-
HttpString() {
117-
this instanceof HttpStringLiteral
118-
or
119-
concatHttpString(this.(AddExpr).getLeftOperand(),
120-
getLeftmostConcatOperand(this.(AddExpr).getRightOperand()))
121-
}
122-
}
123-
124-
/**
125-
* String pattern of basic authentication.
126-
*/
127-
class BasicAuthString extends StringLiteral {
128-
BasicAuthString() { exists(string s | this.getRepresentedString() = s | s.matches("Basic %")) }
129-
}
130-
131-
/**
132-
* String concatenated with `BasicAuthString`.
133-
*/
134-
predicate builtFromBasicAuthStringConcat(Expr expr) {
135-
expr instanceof BasicAuthString
136-
or
137-
builtFromBasicAuthStringConcat(expr.(AddExpr).getLeftOperand())
138-
or
139-
exists(Expr other | builtFromBasicAuthStringConcat(other) |
140-
exists(Variable var | var.getAnAssignedValue() = other and var.getAnAccess() = expr)
141-
)
142-
}
143-
144-
/** The `openConnection` method of Java URL. Not to include `openStream` since it won't be used in this query. */
145-
class HttpURLOpenMethod extends Method {
146-
HttpURLOpenMethod() {
147-
this.getDeclaringType() instanceof TypeUrl and
148-
this.getName() = "openConnection"
149-
}
150-
}
151-
152-
/** Constructor of `ApacheHttpRequest` */
153-
predicate apacheHttpRequest(DataFlow::Node node1, DataFlow::Node node2) {
154-
exists(ConstructorCall cc |
155-
cc.getConstructedType() instanceof ApacheHttpRequest and
156-
node2.asExpr() = cc and
157-
cc.getAnArgument() = node1.asExpr()
158-
)
159-
}
160-
161-
/** `URI` methods */
162-
predicate createURI(DataFlow::Node node1, DataFlow::Node node2) {
163-
exists(
164-
URIConstructor cc // new URI
165-
|
166-
node2.asExpr() = cc and
167-
cc.getArgument(0) = node1.asExpr()
168-
)
169-
or
170-
exists(
171-
StaticMethodAccess ma // URI.create
172-
|
173-
ma.getMethod().getDeclaringType() instanceof TypeUri and
174-
ma.getMethod().hasName("create") and
175-
node1.asExpr() = ma.getArgument(0) and
176-
node2.asExpr() = ma
177-
)
178-
}
179-
180-
/** Constructors of `URL` */
181-
predicate createURL(DataFlow::Node node1, DataFlow::Node node2) {
182-
exists(URLConstructor cc |
183-
node2.asExpr() = cc and
184-
cc.getArgument(0) = node1.asExpr()
185-
)
186-
}
187-
188-
/** Method call of `HttpURLOpenMethod` */
189-
predicate urlOpen(DataFlow::Node node1, DataFlow::Node node2) {
190-
exists(MethodAccess ma |
191-
ma.getMethod() instanceof HttpURLOpenMethod and
192-
node1.asExpr() = ma.getQualifier() and
193-
ma = node2.asExpr()
194-
)
195-
}
196-
19721
class BasicAuthFlowConfig extends TaintTracking::Configuration {
19822
BasicAuthFlowConfig() { this = "InsecureBasicAuth::BasicAuthFlowConfig" }
19923

200-
override predicate isSource(DataFlow::Node src) {
201-
src.asExpr() instanceof HttpString
202-
or
203-
exists(URLConstructor uc |
204-
uc.hasHttpStringArg() and
205-
src.asExpr() = uc.getArgument(0)
206-
)
207-
or
208-
exists(URIConstructor uc |
209-
uc.hasHttpStringArg() and
210-
src.asExpr() = uc.getArgument(0)
211-
)
212-
}
24+
override predicate isSource(DataFlow::Node src) { src instanceof InsecureBasicAuthSource }
21325

214-
override predicate isSink(DataFlow::Node sink) {
215-
exists(MethodAccess ma |
216-
sink.asExpr() = ma.getQualifier() and
217-
(
218-
ma.getMethod().hasName("addHeader") or
219-
ma.getMethod().hasName("setHeader") or
220-
ma.getMethod().hasName("setRequestProperty")
221-
) and
222-
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "Authorization" and
223-
builtFromBasicAuthStringConcat(ma.getArgument(1))
224-
)
225-
}
26+
override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureBasicAuthSink }
22627

22728
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
228-
apacheHttpRequest(node1, node2) or
229-
createURI(node1, node2) or
230-
createURL(node1, node2) or
231-
urlOpen(node1, node2)
29+
any(InsecureBasicAuthAdditionalTaintStep c).step(node1, node2)
23230
}
23331
}
23432

23533
from DataFlow::PathNode source, DataFlow::PathNode sink, BasicAuthFlowConfig config
23634
where config.hasFlowPath(source, sink)
23735
select sink.getNode(), source, sink, "Insecure basic authentication from $@.", source.getNode(),
238-
"HTTP url"
36+
"HTTP URL"

0 commit comments

Comments
 (0)