Move things around after rebase

This commit is contained in:
Tony Torralba
2021-11-12 10:50:07 +01:00
parent 03020582af
commit 101ad777e3
4 changed files with 5 additions and 376 deletions

View File

@@ -1,375 +0,0 @@
/**
* Provides predicates and classes relating to encryption in Java.
*/
import java
class SSLClass extends RefType {
SSLClass() {
exists(Class c | this.getASupertype*() = c |
c.hasQualifiedName("javax.net.ssl", _) or
c.hasQualifiedName("javax.rmi.ssl", _)
)
}
}
class X509TrustManager extends RefType {
X509TrustManager() { this.hasQualifiedName("javax.net.ssl", "X509TrustManager") }
}
class HttpsURLConnection extends RefType {
HttpsURLConnection() { hasQualifiedName("javax.net.ssl", "HttpsURLConnection") }
}
class SSLSocketFactory extends RefType {
SSLSocketFactory() { this.hasQualifiedName("javax.net.ssl", "SSLSocketFactory") }
}
class SSLContext extends RefType {
SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") }
}
/** The `javax.net.ssl.SSLSession` class. */
class SSLSession extends RefType {
SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") }
}
/** The `javax.net.ssl.SSLEngine` class. */
class SSLEngine extends RefType {
SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") }
}
/** The `javax.net.ssl.SSLSocket` class. */
class SSLSocket extends RefType {
SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") }
}
/** The `javax.net.ssl.SSLParameters` class. */
class SSLParameters extends RefType {
SSLParameters() { this.hasQualifiedName("javax.net.ssl", "SSLParameters") }
}
class HostnameVerifier extends RefType {
HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") }
}
/** The Java class `javax.crypto.KeyGenerator`. */
class KeyGenerator extends RefType {
KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") }
}
/** The Java class `java.security.KeyPairGenerator`. */
class KeyPairGenerator extends RefType {
KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") }
}
/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */
class HostnameVerifierVerify extends Method {
HostnameVerifierVerify() {
hasName("verify") and
getDeclaringType().getASupertype*() instanceof HostnameVerifier and
getParameterType(0) instanceof TypeString and
getParameterType(1) instanceof SSLSession
}
}
class TrustManagerCheckMethod extends Method {
TrustManagerCheckMethod() {
(this.hasName("checkClientTrusted") or this.hasName("checkServerTrusted")) and
this.getDeclaringType().getASupertype*() instanceof X509TrustManager
}
}
class CreateSocket extends Method {
CreateSocket() {
hasName("createSocket") and
getDeclaringType() instanceof SSLSocketFactory
}
}
class GetSocketFactory extends Method {
GetSocketFactory() {
hasName("getSocketFactory") and
getDeclaringType() instanceof SSLContext
}
}
/** The `createSSLEngine` method of the class `javax.net.ssl.SSLContext` */
class CreateSslEngineMethod extends Method {
CreateSslEngineMethod() {
this.hasName("createSSLEngine") and
this.getDeclaringType() instanceof SSLContext
}
}
class SetConnectionFactoryMethod extends Method {
SetConnectionFactoryMethod() {
hasName("setSSLSocketFactory") and
getDeclaringType().getASupertype*() instanceof HttpsURLConnection
}
}
class SetHostnameVerifierMethod extends Method {
SetHostnameVerifierMethod() {
hasName("setHostnameVerifier") and
getDeclaringType().getASupertype*() instanceof HttpsURLConnection
}
}
/** The `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */
class SetDefaultHostnameVerifierMethod extends Method {
SetDefaultHostnameVerifierMethod() {
hasName("setDefaultHostnameVerifier") and
getDeclaringType().getASupertype*() instanceof HttpsURLConnection
}
}
/** The `beginHandshake` method of the class `javax.net.ssl.SSLEngine`. */
class BeginHandshakeMethod extends Method {
BeginHandshakeMethod() {
hasName("beginHandshake") and
getDeclaringType().getASupertype*() instanceof SSLEngine
}
}
/** The `wrap` method of the class `javax.net.ssl.SSLEngine`. */
class SslWrapMethod extends Method {
SslWrapMethod() {
hasName("wrap") and
getDeclaringType().getASupertype*() instanceof SSLEngine
}
}
/** The `unwrap` method of the class `javax.net.ssl.SSLEngine`. */
class SslUnwrapMethod extends Method {
SslUnwrapMethod() {
hasName("unwrap") and
getDeclaringType().getASupertype*() instanceof SSLEngine
}
}
bindingset[algorithmString]
private string algorithmRegex(string algorithmString) {
// Algorithms usually appear in names surrounded by characters that are not
// alphabetical characters in the same case. This handles the upper and lower
// case cases.
result =
"((^|.*[^A-Z])(" + algorithmString + ")([^A-Z].*|$))" +
// or...
"|" +
// For lowercase, we want to be careful to avoid being confused by camelCase
// hence we require two preceding uppercase letters to be sure of a case switch,
// or a preceding non-alphabetic character
"((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))"
}
/**
* Gets the name of an algorithm that is known to be insecure.
*/
string getAnInsecureAlgorithmName() {
result =
[
"DES", "RC2", "RC4", "RC5",
// ARCFOUR is a variant of RC4
"ARCFOUR",
// Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks
"ECB",
// CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks
"AES/CBC/PKCS[57]Padding"
]
}
/**
* Gets the name of a hash algorithm that is insecure if it is being used for
* encryption.
*/
string getAnInsecureHashAlgorithmName() {
result = "SHA1" or
result = "MD5"
}
private string rankedInsecureAlgorithm(int i) {
// In this case we know these are being used for encryption, so we want to match
// weak hash algorithms too.
result =
rank[i](string s | s = getAnInsecureAlgorithmName() or s = getAnInsecureHashAlgorithmName())
}
private string insecureAlgorithmString(int i) {
i = 1 and result = rankedInsecureAlgorithm(i)
or
result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1)
}
/**
* Gets the regular expression used for matching strings that look like they
* contain an algorithm that is known to be insecure.
*/
string getInsecureAlgorithmRegex() {
result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i)))))
}
/**
* Gets the name of an algorithm that is known to be secure.
*/
string getASecureAlgorithmName() {
result =
[
"RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*",
"Blowfish", "ECIES"
]
}
private string rankedSecureAlgorithm(int i) { result = rank[i](getASecureAlgorithmName()) }
private string secureAlgorithmString(int i) {
i = 1 and result = rankedSecureAlgorithm(i)
or
result = rankedSecureAlgorithm(i) + "|" + secureAlgorithmString(i - 1)
}
/**
* Gets a regular expression for matching strings that look like they
* contain an algorithm that is known to be secure.
*/
string getSecureAlgorithmRegex() {
result = algorithmRegex(secureAlgorithmString(max(int i | exists(rankedSecureAlgorithm(i)))))
}
/**
* DEPRECATED: Terminology has been updated. Use `getAnInsecureAlgorithmName()`
* instead.
*/
deprecated string algorithmBlacklist() { result = getAnInsecureAlgorithmName() }
/**
* DEPRECATED: Terminology has been updated. Use
* `getAnInsecureHashAlgorithmName()` instead.
*/
deprecated string hashAlgorithmBlacklist() { result = getAnInsecureHashAlgorithmName() }
/**
* DEPRECATED: Terminology has been updated. Use `getInsecureAlgorithmRegex()` instead.
*/
deprecated string algorithmBlacklistRegex() { result = getInsecureAlgorithmRegex() }
/**
* DEPRECATED: Terminology has been updated. Use `getASecureAlgorithmName()`
* instead.
*/
deprecated string algorithmWhitelist() { result = getASecureAlgorithmName() }
/**
* DEPRECATED: Terminology has been updated. Use `getSecureAlgorithmRegex()` instead.
*/
deprecated string algorithmWhitelistRegex() { result = getSecureAlgorithmRegex() }
/**
* Any use of a cryptographic element that specifies an encryption
* algorithm. For example, methods returning ciphers, decryption methods,
* constructors of cipher classes, etc.
*/
abstract class CryptoAlgoSpec extends Top {
CryptoAlgoSpec() { this instanceof Call }
abstract Expr getAlgoSpec();
}
abstract class JavaxCryptoAlgoSpec extends CryptoAlgoSpec { }
class JavaxCryptoCipher extends JavaxCryptoAlgoSpec {
JavaxCryptoCipher() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "javax.crypto.Cipher" and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}
class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec {
JavaxCryptoSecretKey() {
exists(Constructor c | c.getAReference() = this |
c.getDeclaringType().getQualifiedName() = "javax.crypto.spec.SecretKeySpec"
)
}
override Expr getAlgoSpec() {
exists(ConstructorCall c | c = this |
if c.getNumArgument() = 2 then result = c.getArgument(1) else result = c.getArgument(3)
)
}
}
class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec {
JavaxCryptoKeyGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType() instanceof KeyGenerator and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}
class JavaxCryptoKeyAgreement extends JavaxCryptoAlgoSpec {
JavaxCryptoKeyAgreement() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyAgreement" and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}
class JavaxCryptoKeyFactory extends JavaxCryptoAlgoSpec {
JavaxCryptoKeyFactory() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "javax.crypto.SecretKeyFactory" and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}
abstract class JavaSecurityAlgoSpec extends CryptoAlgoSpec { }
class JavaSecurityMessageDigest extends JavaSecurityAlgoSpec {
JavaSecurityMessageDigest() {
exists(Constructor c | c.getAReference() = this |
c.getDeclaringType().hasQualifiedName("java.security", "MessageDigest")
)
or
exists(Method m | m.getAReference() = this |
m.getDeclaringType().hasQualifiedName("java.security", "MessageDigest") and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(Call).getArgument(0) }
}
class JavaSecuritySignature extends JavaSecurityAlgoSpec {
JavaSecuritySignature() {
exists(Constructor c | c.getAReference() = this |
c.getDeclaringType().getQualifiedName() = "java.security.Signature"
)
}
override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) }
}
/** A method call to the Java class `java.security.KeyPairGenerator`. */
class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec {
JavaSecurityKeyPairGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType() instanceof KeyPairGenerator and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}

View File

@@ -1,65 +0,0 @@
/** Provides taint tracking configurations to be used by unsafe certificate trust queries. */
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.UnsafeCertTrust
import semmle.code.java.security.Encryption
/**
* A taint flow configuration for SSL connections created without a proper certificate trust configuration.
*/
class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration {
SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit }
override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation }
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer instanceof SslUnsafeCertTrustSanitizer
}
}
/**
* An SSL object that was assigned a safe `SSLParameters` object and can be considered safe.
*/
private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer {
SslConnectionWithSafeSslParameters() {
exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer |
config.hasFlowTo(safe) and
sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and
DataFlow::localFlow(sanitizer, this)
)
}
}
private class SafeSslParametersFlowConfig extends DataFlow2::Configuration {
SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" }
override predicate isSource(DataFlow::Node source) {
exists(MethodAccess ma |
ma instanceof SafeSetEndpointIdentificationAlgorithm and
DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode()
)
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma, RefType t | t instanceof SSLSocket or t instanceof SSLEngine |
ma.getMethod().hasName("setSSLParameters") and
ma.getMethod().getDeclaringType().getASupertype*() = t and
ma.getArgument(0) = sink.asExpr()
)
}
}
/**
* A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-empty parameter.
*/
private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess {
SafeSetEndpointIdentificationAlgorithm() {
this.getMethod().hasName("setEndpointIdentificationAlgorithm") and
this.getMethod().getDeclaringType() instanceof SSLParameters and
not this.getArgument(0) instanceof NullLiteral and
not this.getArgument(0).(CompileTimeConstantExpr).getStringValue().length() = 0
}
}