Merge pull request #3438 from artem-smotrakov/unsafe-tls

Java: Added a query for unsafe TLS versions
This commit is contained in:
Anders Schack-Mulligen
2020-06-09 14:07:17 +02:00
committed by GitHub
8 changed files with 478 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
public SSLSocket connect(String host, int port)
throws NoSuchAlgorithmException, IOException {
SSLContext context = SSLContext.getInstance("TLSv1.3");
return (SSLSocket) context.getSocketFactory().createSocket(host, port);
}

View File

@@ -0,0 +1,111 @@
import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
import DataFlow
import PathGraph
/**
* A taint-tracking configuration for unsafe SSL and TLS versions.
*/
class UnsafeTlsVersionConfig extends TaintTracking::Configuration {
UnsafeTlsVersionConfig() { this = "UnsafeTlsVersion::UnsafeTlsVersionConfig" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof UnsafeTlsVersion }
override predicate isSink(DataFlow::Node sink) {
sink instanceof SslContextGetInstanceSink or
sink instanceof CreateSslParametersSink or
sink instanceof SslParametersSetProtocolsSink or
sink instanceof SetEnabledProtocolsSink
}
}
/**
* A sink that sets protocol versions in `SSLContext`,
* i.e `SSLContext.getInstance(protocol)`.
*/
class SslContextGetInstanceSink extends DataFlow::ExprNode {
SslContextGetInstanceSink() {
exists(StaticMethodAccess ma, Method m | m = ma.getMethod() |
m.getDeclaringType() instanceof SSLContext and
m.hasName("getInstance") and
ma.getArgument(0) = asExpr()
)
}
}
/**
* A sink that creates `SSLParameters` with specified protocols,
* i.e. `new SSLParameters(ciphersuites, protocols)`.
*/
class CreateSslParametersSink extends DataFlow::ExprNode {
CreateSslParametersSink() {
exists(ConstructorCall cc | cc.getConstructedType() instanceof SSLParameters |
cc.getArgument(1) = asExpr()
)
}
}
/**
* A sink that sets protocol versions for `SSLParameters`,
* i.e. `parameters.setProtocols(versions)`.
*/
class SslParametersSetProtocolsSink extends DataFlow::ExprNode {
SslParametersSetProtocolsSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m.getDeclaringType() instanceof SSLParameters and
m.hasName("setProtocols") and
ma.getArgument(0) = asExpr()
)
}
}
/**
* A sink that sets protocol versions fro `SSLSocket`, `SSLServerSocket` and `SSLEngine`,
* i.e. `socket.setEnabledProtocols(versions)` or `engine.setEnabledProtocols(versions)`.
*/
class SetEnabledProtocolsSink extends DataFlow::ExprNode {
SetEnabledProtocolsSink() {
exists(MethodAccess ma, Method m, RefType type |
m = ma.getMethod() and type = m.getDeclaringType()
|
(
type instanceof SSLSocket or
type instanceof SSLServerSocket or
type instanceof SSLEngine
) and
m.hasName("setEnabledProtocols") and
ma.getArgument(0) = asExpr()
)
}
}
/**
* Insecure SSL and TLS versions supported by JSSE.
*/
class UnsafeTlsVersion extends StringLiteral {
UnsafeTlsVersion() {
getValue() = "SSL" or
getValue() = "SSLv2" or
getValue() = "SSLv3" or
getValue() = "TLS" or
getValue() = "TLSv1" or
getValue() = "TLSv1.1"
}
}
class SSLParameters extends RefType {
SSLParameters() { hasQualifiedName("javax.net.ssl", "SSLParameters") }
}
class SSLSocket extends RefType {
SSLSocket() { hasQualifiedName("javax.net.ssl", "SSLSocket") }
}
class SSLServerSocket extends RefType {
SSLServerSocket() { hasQualifiedName("javax.net.ssl", "SSLServerSocket") }
}
class SSLEngine extends RefType {
SSLEngine() { hasQualifiedName("javax.net.ssl", "SSLEngine") }
}

View File

@@ -0,0 +1,6 @@
public SSLSocket connect(String host, int port)
throws NoSuchAlgorithmException, IOException {
SSLContext context = SSLContext.getInstance("SSLv3");
return (SSLSocket) context.getSocketFactory().createSocket(host, port);
}

View File

@@ -0,0 +1,60 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>Transport Layer Security (TLS) provides a number of security features such as
confidentiality, integrity, replay prevention and authenticatin.
There are several versions of TLS protocols. The latest is TLS 1.3.
Unfortunately, older versions were found to be vulnerable to a number of attacks.</p>
</overview>
<recommendation>
<p>An application should use TLS 1.3. Currenlty, TLS 1.2 is also considered acceptable.</p>
</recommendation>
<example>
<p>The following example shows how a socket with an unsafe TLS version may be created:</p>
<sample src="UnsafeTLSVersion.java" />
<p>The next example creates a socket with the latest TLS version:</p>
<sample src="SaferTLSVersion.java" />
</example>
<references>
<li>
Wikipedia:
<a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">Transport Layer Security</a>
</li>
<li>
OWASP:
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html">Transport Layer Protection Cheat Sheet</a>
</li>
<li>
Java SE Documentation:
<a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">Java Secure Socket Extension (JSSE) Reference Guide</a>
</li>
<li>
Java SE API Specification:
<a href="https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLContext.html">SSLContext</a>
</li>
<li>
Java SE API Specification:
<a href="https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLParameters.html">SSLParameters</a>
</li>
<li>
Java SE API Specification:
<a href="https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLSocket.html">SSLSocket</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,20 @@
/**
* @name Unsafe TLS version
* @description SSL and older TLS versions are known to be vulnerable.
* TLS 1.3 or at least TLS 1.2 should be used.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/unsafe-tls-version
* @tags security
* external/cwe/cwe-327
*/
import java
import SslLib
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeTlsVersionConfig conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ is unsafe", source.getNode(),
source.getNode().asExpr().(StringLiteral).getValue()