Optimize the query

This commit is contained in:
luchua-bc
2021-01-08 21:56:34 +00:00
parent cfc950f803
commit cbaee937d0
5 changed files with 77 additions and 59 deletions

View File

@@ -6,7 +6,7 @@ are vulnerable to brute force attack when too small a key size is used.</p>
</overview>
<recommendation>
<p>The key should be at least 2048-bit long when using RSA and DSA encryption, 224-bit long when using EC encryption, and 128-bit long when using
<p>The key should be at least 2048 bits long when using RSA and DSA encryption, 224 bits long when using EC encryption, and 128 bits long when using
symmetric encryption.</p>
</recommendation>
@@ -24,10 +24,6 @@ symmetric encryption.</p>
CWE.
<a href="https://cwe.mitre.org/data/definitions/326.html">CWE-326: Inadequate Encryption Strength</a>
</li>
<li>
C# implementation of CodeQL
<a href="https://github.com/github/codeql/blob/df29a1636555465527d17668c19c202e365cf502/csharp/ql/src/Security%20Features/InsufficientKeySize.ql">codeql/csharp/ql/src/Security Features/InsufficientKeySize.ql</a>
</li>
</references>
</qhelp>

View File

@@ -11,16 +11,6 @@ import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
/** The Java class `javax.crypto.KeyGenerator`. */
class KeyGenerator extends RefType {
KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") }
}
/** The Java class `javax.crypto.KeyGenerator`. */
class KeyPairGenerator extends RefType {
KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") }
}
/** The Java class `java.security.spec.ECGenParameterSpec`. */
class ECGenParameterSpec extends RefType {
ECGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") }
@@ -42,9 +32,19 @@ class KeyPairGeneratorInitMethod extends Method {
}
}
/** Returns the key size in the EC algorithm string */
bindingset[algorithm]
int getECKeySize(string algorithm) {
algorithm.matches("sec%") and // specification such as "secp256r1"
result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt()
or
algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2"
result = algorithm.regexpCapture("X9.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
}
/** Taint configuration tracking flow from a key generator to a `init` method call. */
class CryptoKeyGeneratorConfiguration extends TaintTracking::Configuration {
CryptoKeyGeneratorConfiguration() { this = "CryptoKeyGeneratorConfiguration" }
class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr())
@@ -59,8 +59,8 @@ class CryptoKeyGeneratorConfiguration extends TaintTracking::Configuration {
}
/** Taint configuration tracking flow from a keypair generator to a `initialize` method call. */
class KeyPairGeneratorConfiguration extends TaintTracking::Configuration {
KeyPairGeneratorConfiguration() { this = "KeyPairGeneratorConfiguration" }
class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration {
KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr())
@@ -75,10 +75,10 @@ class KeyPairGeneratorConfiguration extends TaintTracking::Configuration {
}
/** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */
predicate incorrectUseOfAES(MethodAccess ma, string msg) {
predicate hasShortAESKey(MethodAccess ma, string msg) {
ma.getMethod() instanceof KeyGeneratorInitMethod and
exists(
JavaxCryptoKeyGenerator jcg, CryptoKeyGeneratorConfiguration cc, DataFlow::PathNode source,
JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source,
DataFlow::PathNode dest
|
jcg.getAlgoSpec().(StringLiteral).getValue() = "AES" and
@@ -90,66 +90,55 @@ predicate incorrectUseOfAES(MethodAccess ma, string msg) {
msg = "Key size should be at least 128 bits for AES encryption."
}
/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */
predicate incorrectUseOfDSA(MethodAccess ma, string msg) {
/** Holds if an asymmetric `KeyPairGenerator` is initialized with an insufficient key size. */
bindingset[type]
predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) {
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source,
DataFlow::PathNode dest
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
DataFlow::PathNode source, DataFlow::PathNode dest
|
jpg.getAlgoSpec().(StringLiteral).getValue() = "DSA" and
jpg.getAlgoSpec().(StringLiteral).getValue() = type and
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kc.hasFlowPath(source, dest)
) and
ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and
msg = "Key size should be at least 2048 bits for DSA encryption."
msg = "Key size should be at least 2048 bits for " + type + " encryption."
}
/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */
predicate hasShortDSAKeyPair(MethodAccess ma, string msg) {
hasShortAsymmetricKeyPair(ma, msg, "DSA")
}
/** Holds if a RSA `KeyPairGenerator` is initialized with an insufficient key size. */
predicate incorrectUseOfRSA(MethodAccess ma, string msg) {
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source,
DataFlow::PathNode dest
|
jpg.getAlgoSpec().(StringLiteral).getValue() = "RSA" and
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kc.hasFlowPath(source, dest)
) and
ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and
msg = "Key size should be at least 2048 bits for RSA encryption."
predicate hasShortRSAKeyPair(MethodAccess ma, string msg) {
hasShortAsymmetricKeyPair(ma, msg, "RSA")
}
/** Holds if an EC `KeyPairGenerator` is initialized with an insufficient key size. */
predicate incorrectUseOfEC(MethodAccess ma, string msg) {
predicate hasShortECKeyPair(MethodAccess ma, string msg) {
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source,
DataFlow::PathNode dest, ClassInstanceExpr cie
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
DataFlow::PathNode source, DataFlow::PathNode dest, ClassInstanceExpr cie
|
jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and //ECC variants such as ECDH and ECDSA
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kc.hasFlowPath(source, dest) and
exists(VariableAssign va |
ma.getArgument(0).(VarAccess).getVariable() = va.getDestVar() and
va.getSource() = cie and
cie.getArgument(0)
.(StringLiteral)
.getRepresentedString()
.regexpCapture(".*[a-zA-Z]+([0-9]+)[a-zA-Z]+.*", 1)
.toInt() < 224
)
DataFlow::localExprFlow(cie, ma.getArgument(0)) and
ma.getArgument(0).getType() instanceof ECGenParameterSpec and
getECKeySize(cie.getArgument(0).(StringLiteral).getRepresentedString()) < 224
) and
msg = "Key size should be at least 224 bits for EC encryption."
}
from Expr e, string msg
where
incorrectUseOfAES(e, msg) or
incorrectUseOfDSA(e, msg) or
incorrectUseOfRSA(e, msg) or
incorrectUseOfEC(e, msg)
hasShortAESKey(e, msg) or
hasShortDSAKeyPair(e, msg) or
hasShortRSAKeyPair(e, msg) or
hasShortECKeyPair(e, msg)
select e, msg

View File

@@ -38,6 +38,16 @@ 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() {
@@ -248,7 +258,7 @@ class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec {
class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec {
JavaxCryptoKeyGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyGenerator" and
m.getDeclaringType() instanceof KeyGenerator and
m.getName() = "getInstance"
)
}
@@ -309,7 +319,7 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec {
class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec {
JavaSecurityKeyPairGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "java.security.KeyPairGenerator" and
m.getDeclaringType() instanceof KeyPairGenerator and
m.getName() = "getInstance"
)
}

View File

@@ -2,3 +2,7 @@
| InsufficientKeySize.java:17:9:17:36 | initialize(...) | Key size should be at least 2048 bits for RSA encryption. |
| InsufficientKeySize.java:25:9:25:36 | initialize(...) | Key size should be at least 2048 bits for DSA encryption. |
| InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. |
| InsufficientKeySize.java:38:9:38:67 | initialize(...) | Key size should be at least 224 bits for EC encryption. |
| InsufficientKeySize.java:48:9:48:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. |
| InsufficientKeySize.java:53:9:53:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. |
| InsufficientKeySize.java:58:9:58:40 | initialize(...) | Key size should be at least 224 bits for EC encryption. |

View File

@@ -34,8 +34,27 @@ public class InsufficientKeySize {
keyPairGen5.initialize(ecSpec1);
KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 224
keyPairGen6.initialize(new ECGenParameterSpec("secp112r1"));
KeyPairGenerator keyPairGen7 = KeyPairGenerator.getInstance("EC");
// GOOD: Key size is no less than 224
ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1");
keyPairGen6.initialize(ecSpec2);
keyPairGen7.initialize(ecSpec2);
KeyPairGenerator keyPairGen8 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 224
ECGenParameterSpec ecSpec3 = new ECGenParameterSpec("X9.62 prime192v2");
keyPairGen8.initialize(ecSpec3);
KeyPairGenerator keyPairGen9 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 224
ECGenParameterSpec ecSpec4 = new ECGenParameterSpec("X9.62 c2tnb191v3");
keyPairGen9.initialize(ecSpec4);
KeyPairGenerator keyPairGen10 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 224
ECGenParameterSpec ecSpec5 = new ECGenParameterSpec("sect163k1");
keyPairGen10.initialize(ecSpec5);
}
}