11/**
2- * @name Unsafe implementation of trusting any certificate or missing hostname verification in SSL configuration
2+ * @name Unsafe certificate trust and improper hostname verification
33 * @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.
44 * @kind problem
55 * @id java/unsafe-cert-trust
@@ -39,13 +39,14 @@ class X509TrustAllManagerInit extends MethodAccess {
3939 this .getMethod ( ) .getDeclaringType ( ) instanceof SSLContext and //init method of SSLContext
4040 (
4141 exists ( ArrayInit ai |
42+ this .getArgument ( 1 ) .( ArrayCreationExpr ) .getInit ( ) = ai and
4243 ai .getInit ( 0 ) .( VarAccess ) .getVariable ( ) .getInitializer ( ) .getType ( ) .( Class ) .getASupertype * ( )
4344 instanceof X509TrustAllManager //Scenario of context.init(null, new TrustManager[] { TRUST_ALL_CERTIFICATES }, null);
4445 )
4546 or
4647 exists ( Variable v , ArrayInit ai |
4748 this .getArgument ( 1 ) .( VarAccess ) .getVariable ( ) = v and
48- ai .getParent ( ) = v .getAnAccess ( ) . getVariable ( ) . getAnAssignedValue ( ) and
49+ ai .getParent ( ) = v .getAnAssignedValue ( ) and
4950 ai .getInit ( 0 ) .getType ( ) .( Class ) .getASupertype * ( ) instanceof X509TrustAllManager //Scenario of context.init(null, serverTMs, null);
5051 )
5152 )
@@ -81,7 +82,7 @@ class TrustAllHostnameVerify extends MethodAccess {
8182 )
8283 or
8384 exists ( Variable v |
84- this .getArgument ( 0 ) .( VarAccess ) .getVariable ( ) = v . getAnAccess ( ) . getVariable ( ) and
85+ this .getArgument ( 0 ) .( VarAccess ) .getVariable ( ) = v and
8586 v .getInitializer ( ) .getType ( ) instanceof TrustAllHostnameVerifier //Scenario of HttpsURLConnection.setDefaultHostnameVerifier(verifier);
8687 )
8788 )
@@ -96,6 +97,10 @@ class Socket extends RefType {
9697 Socket ( ) { this .hasQualifiedName ( "java.net" , "Socket" ) }
9798}
9899
100+ class SocketFactory extends RefType {
101+ SocketFactory ( ) { this .hasQualifiedName ( "javax.net" , "SocketFactory" ) }
102+ }
103+
99104class SSLSocket extends RefType {
100105 SSLSocket ( ) { this .hasQualifiedName ( "javax.net.ssl" , "SSLSocket" ) }
101106}
@@ -110,9 +115,9 @@ predicate setEndpointIdentificationAlgorithm(MethodAccess createSSL) {
110115 createSSL = sslo .getAnAssignedValue ( ) and
111116 ma .getQualifier ( ) = sslo .getAnAccess ( ) and
112117 ma .getMethod ( ) .hasName ( "setSSLParameters" ) and
113- ma .getArgument ( 0 ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
118+ ma .getArgument ( 0 ) = sslparams .getAnAccess ( ) and
114119 exists ( MethodAccess setepa |
115- setepa .getQualifier ( ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
120+ setepa .getQualifier ( ) = sslparams .getAnAccess ( ) and
116121 setepa .getMethod ( ) .hasName ( "setEndpointIdentificationAlgorithm" ) and
117122 not setepa .getArgument ( 0 ) instanceof NullLiteral
118123 )
@@ -128,15 +133,26 @@ predicate hasEndpointIdentificationAlgorithm(Variable ssl) {
128133 |
129134 ma .getQualifier ( ) = ssl .getAnAccess ( ) and
130135 ma .getMethod ( ) .hasName ( "setSSLParameters" ) and
131- ma .getArgument ( 0 ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
136+ ma .getArgument ( 0 ) = sslparams .getAnAccess ( ) and
132137 exists ( MethodAccess setepa |
133- setepa .getQualifier ( ) . ( VarAccess ) = sslparams .getAnAccess ( ) and
138+ setepa .getQualifier ( ) = sslparams .getAnAccess ( ) and
134139 setepa .getMethod ( ) .hasName ( "setEndpointIdentificationAlgorithm" ) and
135140 not setepa .getArgument ( 0 ) instanceof NullLiteral
136141 )
137142 )
138143}
139144
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+
140156/**
141157 * SSL object is created in a separate method call or in the same method
142158 */
@@ -145,13 +161,13 @@ predicate hasFlowPath(MethodAccess createSSL, Variable ssl) {
145161 createSSL = ssl .getAnAssignedValue ( )
146162 or
147163 exists ( CastExpr ce |
148- ce .getExpr ( ) . ( MethodAccess ) = createSSL and
164+ ce .getExpr ( ) = createSSL and
149165 ce .getControlFlowNode ( ) .getASuccessor ( ) .( VariableAssign ) .getDestVar ( ) = ssl //With a type cast like SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443);
150166 )
151167 )
152168 or
153169 exists ( MethodAccess tranm |
154- createSSL .getEnclosingCallable ( ) . ( Method ) = tranm .getMethod ( ) and
170+ createSSL .getEnclosingCallable ( ) = tranm .getMethod ( ) and
155171 tranm .getControlFlowNode ( ) .getASuccessor ( ) .( VariableAssign ) .getDestVar ( ) = ssl and
156172 not setEndpointIdentificationAlgorithm ( createSSL ) //Check the scenario of invocation before used in the current method
157173 )
@@ -183,7 +199,9 @@ class SSLEndpointIdentificationNotSet extends MethodAccess {
183199 this .getMethod ( ) .getDeclaringType ( ) instanceof SSLContext //createEngine method of SSLContext
184200 or
185201 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
187205 ) and
188206 exists ( Variable ssl |
189207 hasNoEndpointIdentificationSet ( this , ssl ) and //Not set in itself
@@ -208,12 +226,12 @@ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess {
208226 RabbitMQEnableHostnameVerificationNotSet ( ) {
209227 this .getMethod ( ) .hasName ( "useSslProtocol" ) and
210228 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
214232 not exists ( MethodAccess ma |
215233 ma .getMethod ( ) .hasName ( "enableHostnameVerification" ) and
216- ma .getQualifier ( ) = va . getVariable ( ) .getAnAccess ( )
234+ ma .getQualifier ( ) = v .getAnAccess ( )
217235 )
218236 )
219237 }
0 commit comments