|
10 | 10 | */
|
11 | 11 |
|
12 | 12 | import java
|
13 |
| -import semmle.code.java.controlflow.Guards |
14 | 13 | import semmle.code.java.dataflow.DataFlow
|
15 |
| -import semmle.code.java.dataflow.FlowSources |
16 |
| -import semmle.code.java.security.Encryption |
17 |
| -import semmle.code.java.security.SecurityFlag |
| 14 | +import semmle.code.java.security.InsecureTrustManagerQuery |
18 | 15 | import DataFlow::PathGraph
|
19 | 16 |
|
20 |
| -/** |
21 |
| - * An insecure `X509TrustManager`. |
22 |
| - * An `X509TrustManager` is considered insecure if it never throws a `CertificateException` |
23 |
| - * and therefore implicitly trusts any certificate as valid. |
24 |
| - */ |
25 |
| -class InsecureX509TrustManager extends RefType { |
26 |
| - InsecureX509TrustManager() { |
27 |
| - this.getASupertype*() instanceof X509TrustManager and |
28 |
| - exists(Method m | |
29 |
| - m.getDeclaringType() = this and |
30 |
| - m.hasName("checkServerTrusted") and |
31 |
| - not mayThrowCertificateException(m) |
32 |
| - ) |
33 |
| - } |
34 |
| -} |
35 |
| - |
36 |
| -/** The `java.security.cert.CertificateException` class. */ |
37 |
| -private class CertificateException extends RefType { |
38 |
| - CertificateException() { this.hasQualifiedName("java.security.cert", "CertificateException") } |
39 |
| -} |
40 |
| - |
41 |
| -/** |
42 |
| - * Holds if: |
43 |
| - * - `m` may `throw` a `CertificateException`, or |
44 |
| - * - `m` calls another method that may throw, or |
45 |
| - * - `m` calls a method declared to throw a `CertificateException`, but for which no source is available |
46 |
| - */ |
47 |
| -private predicate mayThrowCertificateException(Method m) { |
48 |
| - exists(ThrowStmt throwStmt | |
49 |
| - throwStmt.getThrownExceptionType().getASupertype*() instanceof CertificateException |
50 |
| - | |
51 |
| - throwStmt.getEnclosingCallable() = m |
52 |
| - ) |
53 |
| - or |
54 |
| - exists(Method otherMethod | m.polyCalls(otherMethod) | |
55 |
| - mayThrowCertificateException(otherMethod) |
56 |
| - or |
57 |
| - not otherMethod.fromSource() and |
58 |
| - otherMethod.getAnException().getType().getASupertype*() instanceof CertificateException |
59 |
| - ) |
60 |
| -} |
61 |
| - |
62 |
| -/** |
63 |
| - * A configuration to model the flow of an `InsecureX509TrustManager` to an `SSLContext.init` call. |
64 |
| - */ |
65 |
| -class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { |
66 |
| - InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } |
67 |
| - |
68 |
| - override predicate isSource(DataFlow::Node source) { |
69 |
| - source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof InsecureX509TrustManager |
70 |
| - } |
71 |
| - |
72 |
| - override predicate isSink(DataFlow::Node sink) { |
73 |
| - exists(MethodAccess ma, Method m | |
74 |
| - m.hasName("init") and |
75 |
| - m.getDeclaringType() instanceof SSLContext and |
76 |
| - ma.getMethod() = m |
77 |
| - | |
78 |
| - ma.getArgument(1) = sink.asExpr() |
79 |
| - ) |
80 |
| - } |
81 |
| -} |
82 |
| - |
83 |
| -/** |
84 |
| - * Flags suggesting a deliberately insecure `TrustManager` usage. |
85 |
| - */ |
86 |
| -private class InsecureTrustManagerFlag extends FlagKind { |
87 |
| - InsecureTrustManagerFlag() { this = "InsecureTrustManagerFlag" } |
88 |
| - |
89 |
| - bindingset[result] |
90 |
| - override string getAFlagName() { |
91 |
| - result |
92 |
| - .regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") and |
93 |
| - result != "equalsIgnoreCase" |
94 |
| - } |
95 |
| -} |
96 |
| - |
97 |
| -/** Gets a guard that represents a (likely) flag controlling an insecure `TrustManager` use. */ |
98 |
| -private Guard getAnInsecureTrustManagerFlagGuard() { |
99 |
| - result = any(InsecureTrustManagerFlag flag).getAFlag().asExpr() |
100 |
| -} |
101 |
| - |
102 |
| -/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ |
103 |
| -private predicate isNodeGuardedByFlag(DataFlow::Node node) { |
104 |
| - exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | |
105 |
| - g = getASecurityFeatureFlagGuard() or g = getAnInsecureTrustManagerFlagGuard() |
106 |
| - ) |
107 |
| -} |
108 |
| - |
109 |
| -from |
110 |
| - DataFlow::PathNode source, DataFlow::PathNode sink, InsecureTrustManagerConfiguration cfg, |
111 |
| - RefType trustManager |
112 |
| -where |
113 |
| - cfg.hasFlowPath(source, sink) and |
114 |
| - not isNodeGuardedByFlag(sink.getNode()) and |
115 |
| - trustManager = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() |
116 |
| -select sink, source, sink, "$@ that is defined $@ and trusts any certificate, is used here.", |
117 |
| - source, "This trustmanager", trustManager, "here" |
| 17 | +from DataFlow::PathNode source, DataFlow::PathNode sink |
| 18 | +where any(InsecureTrustManagerConfiguration cfg).hasFlowPath(source, sink) |
| 19 | +select sink, source, sink, "This $@, that is defined $@, trusts any certificate and is used here.", |
| 20 | + source, "TrustManager", source.getNode().asExpr().(ClassInstanceExpr).getConstructedType(), "here" |
0 commit comments