|
12 | 12 | */
|
13 | 13 |
|
14 | 14 | import java
|
15 |
| -import semmle.code.java.security.Encryption |
| 15 | +import semmle.code.java.dataflow.TaintTracking |
| 16 | +import semmle.code.java.security.UnsafeCertTrust |
16 | 17 |
|
17 |
| -class SSLEngine extends RefType { |
18 |
| - SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } |
19 |
| -} |
20 |
| - |
21 |
| -class Socket extends RefType { |
22 |
| - Socket() { this.hasQualifiedName("java.net", "Socket") } |
23 |
| -} |
| 18 | +class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { |
| 19 | + SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } |
24 | 20 |
|
25 |
| -class SocketFactory extends RefType { |
26 |
| - SocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } |
27 |
| -} |
| 21 | + override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } |
28 | 22 |
|
29 |
| -class SSLSocket extends RefType { |
30 |
| - SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } |
31 |
| -} |
| 23 | + override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } |
32 | 24 |
|
33 |
| -/** |
34 |
| - * has setEndpointIdentificationAlgorithm set correctly |
35 |
| - */ |
36 |
| -predicate setEndpointIdentificationAlgorithm(MethodAccess createSSL) { |
37 |
| - exists( |
38 |
| - Variable sslo, MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set |
39 |
| - | |
40 |
| - createSSL = sslo.getAnAssignedValue() and |
41 |
| - ma.getQualifier() = sslo.getAnAccess() and |
42 |
| - ma.getMethod().hasName("setSSLParameters") and |
43 |
| - ma.getArgument(0) = sslparams.getAnAccess() and |
44 |
| - exists(MethodAccess setepa | |
45 |
| - setepa.getQualifier() = sslparams.getAnAccess() and |
46 |
| - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and |
47 |
| - not setepa.getArgument(0) instanceof NullLiteral |
48 |
| - ) |
49 |
| - ) |
50 |
| -} |
51 |
| - |
52 |
| -/** |
53 |
| - * has setEndpointIdentificationAlgorithm set correctly |
54 |
| - */ |
55 |
| -predicate hasEndpointIdentificationAlgorithm(Variable ssl) { |
56 |
| - exists( |
57 |
| - MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set |
58 |
| - | |
59 |
| - ma.getQualifier() = ssl.getAnAccess() and |
60 |
| - ma.getMethod().hasName("setSSLParameters") and |
61 |
| - ma.getArgument(0) = sslparams.getAnAccess() and |
62 |
| - exists(MethodAccess setepa | |
63 |
| - setepa.getQualifier() = sslparams.getAnAccess() and |
64 |
| - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and |
65 |
| - not setepa.getArgument(0) instanceof NullLiteral |
66 |
| - ) |
67 |
| - ) |
68 |
| -} |
69 |
| - |
70 |
| -/** |
71 |
| - * Cast of Socket to SSLSocket |
72 |
| - */ |
73 |
| -predicate sslCast(MethodAccess createSSL) { |
74 |
| - exists(Variable ssl, CastExpr ce | |
75 |
| - ce.getExpr() = createSSL and |
76 |
| - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and |
77 |
| - ssl.getType() instanceof SSLSocket //With a type cast `SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443)` |
78 |
| - ) |
79 |
| -} |
80 |
| - |
81 |
| -/** |
82 |
| - * SSL object is created in a separate method call or in the same method |
83 |
| - */ |
84 |
| -predicate hasFlowPath(MethodAccess createSSL, Variable ssl) { |
85 |
| - ( |
86 |
| - createSSL = ssl.getAnAssignedValue() |
87 |
| - or |
88 |
| - exists(CastExpr ce | |
89 |
| - ce.getExpr() = createSSL and |
90 |
| - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl //With a type cast like SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); |
91 |
| - ) |
92 |
| - ) |
93 |
| - or |
94 |
| - exists(MethodAccess tranm | |
95 |
| - createSSL.getEnclosingCallable() = tranm.getMethod() and |
96 |
| - tranm.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and |
97 |
| - not setEndpointIdentificationAlgorithm(createSSL) //Check the scenario of invocation before used in the current method |
98 |
| - ) |
99 |
| -} |
100 |
| - |
101 |
| -/** |
102 |
| - * Not have the SSLParameter set |
103 |
| - */ |
104 |
| -predicate hasNoEndpointIdentificationSet(MethodAccess createSSL, Variable ssl) { |
105 |
| - //No setSSLParameters set |
106 |
| - hasFlowPath(createSSL, ssl) and |
107 |
| - not exists(MethodAccess ma | |
108 |
| - ma.getQualifier() = ssl.getAnAccess() and |
109 |
| - ma.getMethod().hasName("setSSLParameters") |
110 |
| - ) |
111 |
| - or |
112 |
| - //No endpointIdentificationAlgorithm set with setSSLParameters |
113 |
| - hasFlowPath(createSSL, ssl) and |
114 |
| - not setEndpointIdentificationAlgorithm(createSSL) |
115 |
| -} |
116 |
| - |
117 |
| -/** |
118 |
| - * The setEndpointIdentificationAlgorithm method of SSLParameters with the ssl engine or socket |
119 |
| - */ |
120 |
| -class SSLEndpointIdentificationNotSet extends MethodAccess { |
121 |
| - SSLEndpointIdentificationNotSet() { |
122 |
| - ( |
123 |
| - this.getMethod().hasName("createSSLEngine") and |
124 |
| - this.getMethod().getDeclaringType() instanceof SSLContext //createEngine method of SSLContext |
125 |
| - or |
126 |
| - this.getMethod().hasName("createSocket") and |
127 |
| - this.getMethod().getDeclaringType() instanceof SocketFactory and |
128 |
| - this.getMethod().getReturnType() instanceof Socket and |
129 |
| - sslCast(this) //createSocket method of SocketFactory |
130 |
| - ) and |
131 |
| - exists(Variable ssl | |
132 |
| - hasNoEndpointIdentificationSet(this, ssl) and //Not set in itself |
133 |
| - not exists(VariableAssign ar, Variable newSsl | |
134 |
| - ar.getSource() = this.getCaller().getAReference() and |
135 |
| - ar.getDestVar() = newSsl and |
136 |
| - hasEndpointIdentificationAlgorithm(newSsl) //Not set in its caller either |
137 |
| - ) |
138 |
| - ) and |
139 |
| - not exists(MethodAccess ma | ma.getMethod() instanceof HostnameVerifierVerify) //Reduce false positives since this method access set default hostname verifier |
140 |
| - } |
141 |
| -} |
142 |
| - |
143 |
| -class RabbitMQConnectionFactory extends RefType { |
144 |
| - RabbitMQConnectionFactory() { this.hasQualifiedName("com.rabbitmq.client", "ConnectionFactory") } |
145 |
| -} |
146 |
| - |
147 |
| -/** |
148 |
| - * The com.rabbitmq.client.ConnectionFactory useSslProtocol method access without enableHostnameVerification |
149 |
| - */ |
150 |
| -class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { |
151 |
| - RabbitMQEnableHostnameVerificationNotSet() { |
152 |
| - this.getMethod().hasName("useSslProtocol") and |
153 |
| - this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and |
154 |
| - exists(Variable v | |
155 |
| - v.getType() instanceof RabbitMQConnectionFactory and |
156 |
| - this.getQualifier() = v.getAnAccess() and |
157 |
| - not exists(MethodAccess ma | |
158 |
| - ma.getMethod().hasName("enableHostnameVerification") and |
159 |
| - ma.getQualifier() = v.getAnAccess() |
160 |
| - ) |
161 |
| - ) |
| 25 | + override predicate isSanitizer(DataFlow::Node sanitizer) { |
| 26 | + sanitizer.asExpr() instanceof SslConnectionWithSafeSslParameters |
162 | 27 | }
|
163 | 28 | }
|
164 | 29 |
|
165 |
| -from MethodAccess aa |
| 30 | +from Expr unsafeConfig |
166 | 31 | where
|
167 |
| - aa instanceof SSLEndpointIdentificationNotSet or |
168 |
| - aa instanceof RabbitMQEnableHostnameVerificationNotSet |
169 |
| -select aa, "Unsafe configuration of trusted certificates" |
| 32 | + unsafeConfig instanceof RabbitMQEnableHostnameVerificationNotSet or |
| 33 | + exists(SslEndpointIdentificationFlowConfig config | |
| 34 | + config.hasFlowTo(DataFlow::exprNode(unsafeConfig)) |
| 35 | + ) |
| 36 | +select unsafeConfig, "Unsafe configuration of trusted certificates" |
0 commit comments