mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Python: Weak crypto query.
This commit is contained in:
0
python/ql/src/Security/CWE-326/WeakCrypto.qhelp
Normal file
0
python/ql/src/Security/CWE-326/WeakCrypto.qhelp
Normal file
84
python/ql/src/Security/CWE-326/WeakCrypto.ql
Normal file
84
python/ql/src/Security/CWE-326/WeakCrypto.ql
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* @name Weak Cryptographic Key Use
|
||||||
|
* @description Use of a cryptographic key that is too small may allow the encryption to be broken.
|
||||||
|
* @kind problem
|
||||||
|
* @problem.severity error
|
||||||
|
* @precision high
|
||||||
|
* @id py/weak-crypto-key
|
||||||
|
* @tags security
|
||||||
|
* external/cwe/cwe-326
|
||||||
|
*/
|
||||||
|
|
||||||
|
import python
|
||||||
|
|
||||||
|
int minimumSecureKeySize(string algo) {
|
||||||
|
algo = "DSA" and result = 2048
|
||||||
|
or
|
||||||
|
algo = "RSA" and result = 2048
|
||||||
|
or
|
||||||
|
algo = "elliptic curve" and result = 224
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate dsaRsaKeySizeArg(FunctionObject obj, string algorithm, string arg) {
|
||||||
|
exists(ModuleObject mod |
|
||||||
|
mod.getAttribute(_) = obj |
|
||||||
|
algorithm = "DSA" and
|
||||||
|
(
|
||||||
|
mod.getName() = "cryptography.hazmat.primitives.asymmetric.dsa" and arg = "key_size"
|
||||||
|
or
|
||||||
|
mod.getName() = "Crypto.PublicKey.DSA" and arg = "bits"
|
||||||
|
or
|
||||||
|
mod.getName() = "Cryptodome.PublicKey.DSA" and arg = "bits"
|
||||||
|
)
|
||||||
|
or
|
||||||
|
algorithm = "RSA" and
|
||||||
|
(
|
||||||
|
mod.getName() = "cryptography.hazmat.primitives.asymmetric.rsa" and arg = "key_size"
|
||||||
|
or
|
||||||
|
mod.getName() = "Crypto.PublicKey.RSA" and arg = "bits"
|
||||||
|
or
|
||||||
|
mod.getName() = "Cryptodome.PublicKey.RSA" and arg = "bits"
|
||||||
|
)
|
||||||
|
or
|
||||||
|
algorithm = "elliptic curve" and
|
||||||
|
mod.getName() = "cryptography.hazmat.primitives.asymmetric.ec" and arg = "curve"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate ecKeySizeArg(FunctionObject obj, string arg) {
|
||||||
|
exists(ModuleObject mod |
|
||||||
|
mod.getAttribute(_) = obj |
|
||||||
|
mod.getName() = "cryptography.hazmat.primitives.asymmetric.ec" and arg = "curve"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
int keySizeFromCurve(ClassObject curveClass) {
|
||||||
|
result = curveClass.declaredAttribute("key_size").(NumericObject).intValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate algorithmAndKeysizeForCall(CallNode call, string algorithm, int keySize, ControlFlowNode keyOrigin) {
|
||||||
|
exists(FunctionObject func, string argname, ControlFlowNode arg |
|
||||||
|
arg = func.getNamedArgumentForCall(call, argname) |
|
||||||
|
exists(NumericObject key |
|
||||||
|
arg.refersTo(key, keyOrigin) and
|
||||||
|
dsaRsaKeySizeArg(func, algorithm, argname) and
|
||||||
|
keySize = key.intValue()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(ClassObject curve |
|
||||||
|
arg.refersTo(_, curve, keyOrigin) and
|
||||||
|
ecKeySizeArg(func, argname) and
|
||||||
|
algorithm = "elliptic curve" and
|
||||||
|
keySize = keySizeFromCurve(curve)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
from CallNode call, ControlFlowNode origin, string algo, int keySize
|
||||||
|
where
|
||||||
|
algorithmAndKeysizeForCall(call, algo, keySize, origin) and
|
||||||
|
keySize < minimumSecureKeySize(algo)
|
||||||
|
select call, "Creation of an " + algo + " key uses $@ bits, which is below " + minimumSecureKeySize(algo) + " and considered breakable.", origin, keySize.toString()
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
| weak_crypto.py:67:1:67:30 | ControlFlowNode for dsa_gen_key() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
|
||||||
|
| weak_crypto.py:68:1:68:28 | ControlFlowNode for ec_gen_key() | Creation of an elliptic curve key uses $@ bits, which is below 224 and considered breakable. | weak_crypto.py:21:11:21:33 | ControlFlowNode for FakeWeakEllipticCurve() | 160 |
|
||||||
|
| weak_crypto.py:69:1:69:37 | ControlFlowNode for rsa_gen_key() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
|
||||||
|
| weak_crypto.py:71:1:71:22 | ControlFlowNode for Attribute() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
|
||||||
|
| weak_crypto.py:72:1:72:22 | ControlFlowNode for Attribute() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Security/CWE-326/WeakCrypto.ql
|
||||||
2
python/ql/test/query-tests/Security/CWE-326/options
Normal file
2
python/ql/test/query-tests/Security/CWE-326/options
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
semmle-extractor-options: -p ../lib/ --max-import-depth=3
|
||||||
|
optimize: true
|
||||||
73
python/ql/test/query-tests/Security/CWE-326/weak_crypto.py
Normal file
73
python/ql/test/query-tests/Security/CWE-326/weak_crypto.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from cryptography.hazmat import backends
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import ec, dsa, rsa
|
||||||
|
|
||||||
|
#Crypto and Cryptodome have same API
|
||||||
|
if random():
|
||||||
|
from Crypto.PublicKey import DSA
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
else:
|
||||||
|
from Cryptodome.PublicKey import DSA
|
||||||
|
from Cryptodome.PublicKey import RSA
|
||||||
|
|
||||||
|
RSA_WEAK = 1024
|
||||||
|
RSA_OK = 2048
|
||||||
|
RSA_STRONG = 3076
|
||||||
|
BIG = 10000
|
||||||
|
|
||||||
|
class FakeWeakEllipticCurve:
|
||||||
|
name = "fake"
|
||||||
|
key_size = 160
|
||||||
|
|
||||||
|
EC_WEAK = FakeWeakEllipticCurve()
|
||||||
|
EC_OK = ec.SECP224R1()
|
||||||
|
EC_STRONG = ec.SECP384R1()
|
||||||
|
EC_BIG = ec.SECT571R1()
|
||||||
|
|
||||||
|
dsa_gen_key = dsa.generate_private_key
|
||||||
|
ec_gen_key = ec.generate_private_key
|
||||||
|
rsa_gen_key = rsa.generate_private_key
|
||||||
|
|
||||||
|
default = backends.default_backend()
|
||||||
|
|
||||||
|
#Strong and OK keys.
|
||||||
|
|
||||||
|
dsa_gen_key(key_size=RSA_OK, backend=default)
|
||||||
|
dsa_gen_key(key_size=RSA_STRONG, backend=default)
|
||||||
|
dsa_gen_key(key_size=BIG, backend=default)
|
||||||
|
ec_gen_key(key_size=EC_OK, backend=default)
|
||||||
|
ec_gen_key(key_size=EC_STRONG, backend=default)
|
||||||
|
ec_gen_key(key_size=EC_BIG, backend=default)
|
||||||
|
rsa_gen_key(public_exponent=65537, key_size=RSA_OK, backend=default)
|
||||||
|
rsa_gen_key(public_exponent=65537, key_size=RSA_STRONG, backend=default)
|
||||||
|
rsa_gen_key(public_exponent=65537, key_size=BIG, backend=default)
|
||||||
|
|
||||||
|
DSA.generate(bits=RSA_OK)
|
||||||
|
DSA.generate(bits=RSA_STRONG)
|
||||||
|
RSA.generate(bits=RSA_OK)
|
||||||
|
RSA.generate(bits=RSA_STRONG)
|
||||||
|
|
||||||
|
dsa_gen_key(RSA_OK, default)
|
||||||
|
dsa_gen_key(RSA_STRONG, default)
|
||||||
|
dsa_gen_key(BIG, default)
|
||||||
|
ec_gen_key(EC_OK, default)
|
||||||
|
ec_gen_key(EC_STRONG, default)
|
||||||
|
ec_gen_key(EC_BIG, default)
|
||||||
|
rsa_gen_key(65537, RSA_OK, default)
|
||||||
|
rsa_gen_key(65537, RSA_STRONG, default)
|
||||||
|
rsa_gen_key(65537, BIG, default)
|
||||||
|
|
||||||
|
DSA.generate(RSA_OK)
|
||||||
|
DSA.generate(RSA_STRONG)
|
||||||
|
RSA.generate(RSA_OK)
|
||||||
|
RSA.generate(RSA_STRONG)
|
||||||
|
|
||||||
|
|
||||||
|
# Weak keys
|
||||||
|
|
||||||
|
dsa_gen_key(RSA_WEAK, default)
|
||||||
|
ec_gen_key(EC_WEAK, default)
|
||||||
|
rsa_gen_key(65537, RSA_WEAK, default)
|
||||||
|
|
||||||
|
DSA.generate(RSA_WEAK)
|
||||||
|
RSA.generate(RSA_WEAK)
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def generate(bits):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def generate(bits):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
def generate_private_key(key_size, backend):
|
||||||
|
pass
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
def generate_private_key(curve, backend):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SECT571R1(object):
|
||||||
|
name = "sect571r1"
|
||||||
|
key_size = 570
|
||||||
|
|
||||||
|
|
||||||
|
class SECP384R1(object):
|
||||||
|
name = "secp384r1"
|
||||||
|
key_size = 384
|
||||||
|
|
||||||
|
|
||||||
|
class SECP224R1(object):
|
||||||
|
name = "secp224r1"
|
||||||
|
key_size = 224
|
||||||
|
|
||||||
|
|
||||||
|
class SECT163K1(object):
|
||||||
|
name = "sect163k1"
|
||||||
|
key_size = 163
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
def generate_private_key(public_exponent, key_size, backend):
|
||||||
|
pass
|
||||||
Reference in New Issue
Block a user