|
11 | 11 | */
|
12 | 12 |
|
13 | 13 | import java
|
14 |
| -import semmle.code.java.controlflow.Guards |
15 |
| -import semmle.code.java.dataflow.DataFlow |
16 |
| -import semmle.code.java.dataflow.FlowSources |
17 |
| -import semmle.code.java.security.Encryption |
18 |
| -import semmle.code.java.security.SecurityFlag |
19 |
| -private import semmle.code.java.dataflow.ExternalFlow |
20 |
| - |
21 |
| -/** |
22 |
| - * Holds if `m` always returns `true` ignoring any exceptional flow. |
23 |
| - */ |
24 |
| -private predicate alwaysReturnsTrue(HostnameVerifierVerify m) { |
25 |
| - forex(ReturnStmt rs | rs.getEnclosingCallable() = m | |
26 |
| - rs.getResult().(CompileTimeConstantExpr).getBooleanValue() = true |
27 |
| - ) |
28 |
| -} |
29 |
| - |
30 |
| -/** |
31 |
| - * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true` (though it could also exit due to an uncaught exception), thus |
32 |
| - * accepting any certificate despite a hostname mismatch. |
33 |
| - */ |
34 |
| -class TrustAllHostnameVerifier extends RefType { |
35 |
| - TrustAllHostnameVerifier() { |
36 |
| - this.getAnAncestor() instanceof HostnameVerifier and |
37 |
| - exists(HostnameVerifierVerify m | |
38 |
| - m.getDeclaringType() = this and |
39 |
| - alwaysReturnsTrue(m) |
40 |
| - ) |
41 |
| - } |
42 |
| -} |
43 |
| - |
44 |
| -/** |
45 |
| - * A configuration to model the flow of a `TrustAllHostnameVerifier` to a `set(Default)HostnameVerifier` call. |
46 |
| - */ |
47 |
| -module TrustAllHostnameVerifierConfig implements DataFlow::ConfigSig { |
48 |
| - predicate isSource(DataFlow::Node source) { |
49 |
| - source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof TrustAllHostnameVerifier |
50 |
| - } |
51 |
| - |
52 |
| - predicate isSink(DataFlow::Node sink) { sink instanceof HostnameVerifierSink } |
53 |
| - |
54 |
| - predicate isBarrier(DataFlow::Node barrier) { |
55 |
| - // ignore nodes that are in functions that intentionally disable hostname verification |
56 |
| - barrier |
57 |
| - .getEnclosingCallable() |
58 |
| - .getName() |
59 |
| - /* |
60 |
| - * Regex: (_)* : |
61 |
| - * some methods have underscores. |
62 |
| - * Regex: (no|ignore|disable)(strictssl|ssl|verify|verification|hostname) |
63 |
| - * noStrictSSL ignoreSsl |
64 |
| - * Regex: (set)?(accept|trust|ignore|allow)(all|every|any) |
65 |
| - * acceptAll trustAll ignoreAll setTrustAnyHttps |
66 |
| - * Regex: (use|do|enable)insecure |
67 |
| - * useInsecureSSL |
68 |
| - * Regex: (set|do|use)?no.*(check|validation|verify|verification) |
69 |
| - * setNoCertificateCheck |
70 |
| - * Regex: disable |
71 |
| - * disableChecks |
72 |
| - */ |
73 |
| - |
74 |
| - .regexpMatch("^(?i)(_)*((no|ignore|disable)(strictssl|ssl|verify|verification|hostname)" + |
75 |
| - "|(set)?(accept|trust|ignore|allow)(all|every|any)" + |
76 |
| - "|(use|do|enable)insecure|(set|do|use)?no.*(check|validation|verify|verification)|disable).*$") |
77 |
| - } |
78 |
| -} |
79 |
| - |
80 |
| -module TrustAllHostnameVerifierFlow = DataFlow::Global<TrustAllHostnameVerifierConfig>; |
81 |
| - |
| 14 | +import semmle.code.java.security.UnsafeHostnameVerificationQuery |
82 | 15 | import TrustAllHostnameVerifierFlow::PathGraph
|
83 | 16 |
|
84 |
| -/** |
85 |
| - * A sink that sets the `HostnameVerifier` on `HttpsURLConnection`. |
86 |
| - */ |
87 |
| -private class HostnameVerifierSink extends DataFlow::Node { |
88 |
| - HostnameVerifierSink() { sinkNode(this, "set-hostname-verifier") } |
89 |
| -} |
90 |
| - |
91 |
| -/** |
92 |
| - * Flags suggesting a deliberately unsafe `HostnameVerifier` usage. |
93 |
| - */ |
94 |
| -private class UnsafeHostnameVerificationFlag extends FlagKind { |
95 |
| - UnsafeHostnameVerificationFlag() { this = "UnsafeHostnameVerificationFlag" } |
96 |
| - |
97 |
| - bindingset[result] |
98 |
| - override string getAFlagName() { |
99 |
| - result |
100 |
| - .regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") and |
101 |
| - result != "equalsIgnoreCase" |
102 |
| - } |
103 |
| -} |
104 |
| - |
105 |
| -/** Gets a guard that represents a (likely) flag controlling an unsafe `HostnameVerifier` use. */ |
106 |
| -private Guard getAnUnsafeHostnameVerifierFlagGuard() { |
107 |
| - result = any(UnsafeHostnameVerificationFlag flag).getAFlag().asExpr() |
108 |
| -} |
109 |
| - |
110 |
| -/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ |
111 |
| -private predicate isNodeGuardedByFlag(DataFlow::Node node) { |
112 |
| - exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | |
113 |
| - g = getASecurityFeatureFlagGuard() or g = getAnUnsafeHostnameVerifierFlagGuard() |
114 |
| - ) |
115 |
| -} |
116 |
| - |
117 | 17 | from
|
118 | 18 | TrustAllHostnameVerifierFlow::PathNode source, TrustAllHostnameVerifierFlow::PathNode sink,
|
119 | 19 | RefType verifier
|
|
0 commit comments