1
1
/**
2
- * @name Unsafe implementation of trusting any certificate or missing hostname verification in SSL configuration
2
+ * @name Unsafe certificate trust and improper hostname verification
3
3
* @description Unsafe implementation of the interface X509TrustManager, HostnameVerifier, and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.
4
4
* @kind problem
5
5
* @id java/unsafe-cert-trust
@@ -39,13 +39,14 @@ class X509TrustAllManagerInit extends MethodAccess {
39
39
this .getMethod ( ) .getDeclaringType ( ) instanceof SSLContext and //init method of SSLContext
40
40
(
41
41
exists ( ArrayInit ai |
42
+ this .getArgument ( 1 ) .( ArrayCreationExpr ) .getInit ( ) = ai and
42
43
ai .getInit ( 0 ) .( VarAccess ) .getVariable ( ) .getInitializer ( ) .getType ( ) .( Class ) .getASupertype * ( )
43
44
instanceof X509TrustAllManager //Scenario of context.init(null, new TrustManager[] { TRUST_ALL_CERTIFICATES }, null);
44
45
)
45
46
or
46
47
exists ( Variable v , ArrayInit ai |
47
48
this .getArgument ( 1 ) .( VarAccess ) .getVariable ( ) = v and
48
- ai .getParent ( ) = v .getAnAccess ( ) . getVariable ( ) . getAnAssignedValue ( ) and
49
+ ai .getParent ( ) = v .getAnAssignedValue ( ) and
49
50
ai .getInit ( 0 ) .getType ( ) .( Class ) .getASupertype * ( ) instanceof X509TrustAllManager //Scenario of context.init(null, serverTMs, null);
50
51
)
51
52
)
@@ -81,7 +82,7 @@ class TrustAllHostnameVerify extends MethodAccess {
81
82
)
82
83
or
83
84
exists ( Variable v |
84
- this .getArgument ( 0 ) .( VarAccess ) .getVariable ( ) = v . getAnAccess ( ) . getVariable ( ) and
85
+ this .getArgument ( 0 ) .( VarAccess ) .getVariable ( ) = v and
85
86
v .getInitializer ( ) .getType ( ) instanceof TrustAllHostnameVerifier //Scenario of HttpsURLConnection.setDefaultHostnameVerifier(verifier);
86
87
)
87
88
)
@@ -96,6 +97,10 @@ class Socket extends RefType {
96
97
Socket ( ) { this .hasQualifiedName ( "java.net" , "Socket" ) }
97
98
}
98
99
100
+ class SocketFactory extends RefType {
101
+ SocketFactory ( ) { this .hasQualifiedName ( "javax.net" , "SocketFactory" ) }
102
+ }
103
+
99
104
class SSLSocket extends RefType {
100
105
SSLSocket ( ) { this .hasQualifiedName ( "javax.net.ssl" , "SSLSocket" ) }
101
106
}
@@ -110,9 +115,9 @@ predicate setEndpointIdentificationAlgorithm(MethodAccess createSSL) {
110
115
createSSL = sslo .getAnAssignedValue ( ) and
111
116
ma .getQualifier ( ) = sslo .getAnAccess ( ) and
112
117
ma .getMethod ( ) .hasName ( "setSSLParameters" ) and
113
- ma .getArgument ( 0 ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
118
+ ma .getArgument ( 0 ) = sslparams .getAnAccess ( ) and
114
119
exists ( MethodAccess setepa |
115
- setepa .getQualifier ( ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
120
+ setepa .getQualifier ( ) = sslparams .getAnAccess ( ) and
116
121
setepa .getMethod ( ) .hasName ( "setEndpointIdentificationAlgorithm" ) and
117
122
not setepa .getArgument ( 0 ) instanceof NullLiteral
118
123
)
@@ -128,15 +133,26 @@ predicate hasEndpointIdentificationAlgorithm(Variable ssl) {
128
133
|
129
134
ma .getQualifier ( ) = ssl .getAnAccess ( ) and
130
135
ma .getMethod ( ) .hasName ( "setSSLParameters" ) and
131
- ma .getArgument ( 0 ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
136
+ ma .getArgument ( 0 ) = sslparams .getAnAccess ( ) and
132
137
exists ( MethodAccess setepa |
133
- setepa .getQualifier ( ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
138
+ setepa .getQualifier ( ) = sslparams .getAnAccess ( ) and
134
139
setepa .getMethod ( ) .hasName ( "setEndpointIdentificationAlgorithm" ) and
135
140
not setepa .getArgument ( 0 ) instanceof NullLiteral
136
141
)
137
142
)
138
143
}
139
144
145
+ /**
146
+ * Cast of Socket to SSLSocket
147
+ */
148
+ predicate sslCast ( MethodAccess createSSL ) {
149
+ exists ( Variable ssl , CastExpr ce |
150
+ ce .getExpr ( ) = createSSL and
151
+ ce .getControlFlowNode ( ) .getASuccessor ( ) .( VariableAssign ) .getDestVar ( ) = ssl and
152
+ ssl .getType ( ) instanceof SSLSocket //With a type cast `SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443)`
153
+ )
154
+ }
155
+
140
156
/**
141
157
* SSL object is created in a separate method call or in the same method
142
158
*/
@@ -145,13 +161,13 @@ predicate hasFlowPath(MethodAccess createSSL, Variable ssl) {
145
161
createSSL = ssl .getAnAssignedValue ( )
146
162
or
147
163
exists ( CastExpr ce |
148
- ce .getExpr ( ) . ( MethodAccess ) = createSSL and
164
+ ce .getExpr ( ) = createSSL and
149
165
ce .getControlFlowNode ( ) .getASuccessor ( ) .( VariableAssign ) .getDestVar ( ) = ssl //With a type cast like SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443);
150
166
)
151
167
)
152
168
or
153
169
exists ( MethodAccess tranm |
154
- createSSL .getEnclosingCallable ( ) . ( Method ) = tranm .getMethod ( ) and
170
+ createSSL .getEnclosingCallable ( ) = tranm .getMethod ( ) and
155
171
tranm .getControlFlowNode ( ) .getASuccessor ( ) .( VariableAssign ) .getDestVar ( ) = ssl and
156
172
not setEndpointIdentificationAlgorithm ( createSSL ) //Check the scenario of invocation before used in the current method
157
173
)
@@ -183,7 +199,9 @@ class SSLEndpointIdentificationNotSet extends MethodAccess {
183
199
this .getMethod ( ) .getDeclaringType ( ) instanceof SSLContext //createEngine method of SSLContext
184
200
or
185
201
this .getMethod ( ) .hasName ( "createSocket" ) and
186
- this .getMethod ( ) .getReturnType ( ) instanceof Socket //createSocket method of SSLSocketFactory
202
+ this .getMethod ( ) .getDeclaringType ( ) instanceof SocketFactory and
203
+ this .getMethod ( ) .getReturnType ( ) instanceof Socket and
204
+ sslCast ( this ) //createSocket method of SocketFactory
187
205
) and
188
206
exists ( Variable ssl |
189
207
hasNoEndpointIdentificationSet ( this , ssl ) and //Not set in itself
@@ -208,12 +226,12 @@ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess {
208
226
RabbitMQEnableHostnameVerificationNotSet ( ) {
209
227
this .getMethod ( ) .hasName ( "useSslProtocol" ) and
210
228
this .getMethod ( ) .getDeclaringType ( ) instanceof RabbitMQConnectionFactory and
211
- exists ( VarAccess va |
212
- va . getVariable ( ) .getType ( ) instanceof RabbitMQConnectionFactory and
213
- this .getQualifier ( ) = va . getVariable ( ) .getAnAccess ( ) and
229
+ exists ( Variable v |
230
+ v .getType ( ) instanceof RabbitMQConnectionFactory and
231
+ this .getQualifier ( ) = v .getAnAccess ( ) and
214
232
not exists ( MethodAccess ma |
215
233
ma .getMethod ( ) .hasName ( "enableHostnameVerification" ) and
216
- ma .getQualifier ( ) = va . getVariable ( ) .getAnAccess ( )
234
+ ma .getQualifier ( ) = v .getAnAccess ( )
217
235
)
218
236
)
219
237
}
0 commit comments