Skip to content

[WIP] Java: Improve CWE 295 #4536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

intrigus-lgtm
Copy link
Contributor

Continuation of #3581
@smowton what do you think about the approach?
I.e. using data flow and splitting everything into unsafe trustmanager, trust-all hostname verifier, and missing SSL endpoint indentification?

This seperates security issues with missing hostname verification
(CWE 297)
and issues with trustmanagers that accept any certificate as valid
(CWE 295).
(This is an incomplete separation for now)
Separate trust-all hostname verification and
cases that miss enabling SSL endpoint identification.
Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitting this partial review, but I think I may have partially reviewed commits that are subsequently undone. Will now switch to reviewing the whole changeset as a single unit.

Comment on lines +16 to +18
public X509Certificate[] getAcceptedIssuers() {
return null; //BAD: doesn't check cert issuer
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? All the uses in the JDK I can find seem to treat a null return as either invalid, or equivalent to a zero-length return (i.e., trust nobody).

Comment on lines +36 to +38
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0]; //GOOD: Validate the cert issuer
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely this rejects everything?

</li>
<li>
<a href="https://support.google.com/faqs/answer/6346016?hl=en">How to fix apps containing an unsafe implementation of TrustManager</a>
<a href="https://support.google.com/faqs/answer/7188426?hl=en">How to resolve Insecure HostnameVerifier</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to find a link that doesn't specifically talk about Google Play, since this query is more general than that.

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these comments are improvements to code that's already committed to experimental, so they're optional.

Could you clarify which cases you think are now covered that were not previously covered by the CWE-273 query?

<qhelp>

<overview>
<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
<p>Java offers two mechanisms for SSL authentication - the X509 trust manager and the hostname verifier. The X509 trust manager validates the peer's certificate chain, while hostname verification establishes that the hostname in the URL matches the hostname given by the peer's certificate.</p>


<overview>
<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
<p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
<p>Note that SSLSocket and SSLEngine do not verify hostnames by default. Verification must be enabled by calling <code>setEndpointIdentificationAlgorithm</code>.</p>

<overview>
<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
<p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
<p>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.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>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.</p>
<p>Unsafe implementations of the interfaces <code>X509TrustManager</code>, <code>HostnameVerifier</code>, and <code>SSLSocket</code>/<code>SSLEngine</code> that ignore SSL certificate validation errors when establishing an HTTPS connection make the connection vulnerable to man-in-the-middle attacks.</p>

<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
<p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
<p>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.</p>
<p>This query checks whether trust manager is set to trust all certificates, the hostname verifier is turned off, or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>This query checks whether trust manager is set to trust all certificates, the hostname verifier is turned off, or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p>
<p>This query checks whether trust manager is set to trust all certificates, the hostname verifier is turned off, or <code>setEndpointIdentificationAlgorithm</code> is missing. The query also covers an insecure implementation <code>com.rabbitmq.client.ConnectionFactory</code>.</p>

Comment on lines +25 to +28
m2.getDeclaringType() = this and
m2.hasName("getAcceptedIssuers") and
rt2.getEnclosingCallable() = m2 and
rt2.getResult() instanceof NullLiteral
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment from previous review still applies: this doesn't seem to be a problem

Comment on lines +41 to +51
exists(ArrayInit ai |
this.getArgument(1).(ArrayCreationExpr).getInit() = ai and
ai.getInit(0).(VarAccess).getVariable().getInitializer().getType().(Class).getASupertype*()
instanceof X509TrustAllManager //Scenario of context.init(null, new TrustManager[] { TRUST_ALL_CERTIFICATES }, null);
)
or
exists(Variable v, ArrayInit ai |
this.getArgument(1).(VarAccess).getVariable() = v and
ai.getParent() = v.getAnAssignedValue() and
ai.getInit(0).getType().(Class).getASupertype*() instanceof X509TrustAllManager //Scenario of context.init(null, serverTMs, null);
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment from previous review still applies: avoid using brittle precise syntax like this; instead use function models to follow taint (in this case indicating an insecure config) from the instantiation of the weak checker through to use in an SSLSocket or similar.

@intrigus-lgtm
Copy link
Contributor Author

Superseded by #4771

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants