-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rule to check for insufficient key size to HMAC
HMAC algorithms require a minimum key size that corresponds to their digest size. Using a size less than the digest size is considered weak. Signed-off-by: Eric Brown <eric.brown@securesauce.dev>
- Loading branch information
Showing
61 changed files
with
482 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
# Copyright 2024 Secure Saurce LLC | ||
r""" | ||
# Inadequate Encryption Strength Using Weak Keys in SSLContext | ||
Using weak key sizes for cryptographic algorithms like Elliptic Curve can | ||
compromise the security of your encryption and digital signatures. Here's | ||
a brief overview of the risks associated with weak key sizes for this | ||
algorithm: | ||
Elliptic Curve cryptography provides strong security with relatively small | ||
key sizes compared to RSA and DSA. However, even in the case of EC, using | ||
weak curve parameters or small key sizes can expose you to vulnerabilities. | ||
The strength of an EC key depends on the curve's properties and the size of | ||
the prime used. | ||
Recommended EC key sizes depend on the curve you select, but for modern | ||
applications, curves like NIST P-256 (secp256r1) with a 256-bit key size | ||
are considered secure. Larger curves, like NIST P-384 or P-521, can provide | ||
even higher security margins. | ||
## Example | ||
```python | ||
import ssl | ||
context = ssl.SSLContext() | ||
context.set_ecdh_curve("prime192v1") | ||
``` | ||
## Remediation | ||
Its recommended to increase the key size to at least 224 EC algorithms. | ||
```python | ||
import ssl | ||
context = ssl.SSLContext() | ||
context.set_ecdh_curve("prime256v1") | ||
``` | ||
## See also | ||
- [hmac — Keyed-Hashing for Message Authentication](https://docs.python.org/3/library/hmac.html) | ||
- [CWE-326: Inadequate Encryption Strength](https://cwe.mitre.org/data/definitions/326.html) | ||
_New in version 0.4.3_ | ||
""" # noqa: E501 | ||
from precli.core.call import Call | ||
from precli.core.location import Location | ||
from precli.core.result import Result | ||
from precli.rules import Rule | ||
|
||
|
||
HASH_NAME_SIZES = { | ||
"blake2s": 32, | ||
"blake2b": 64, | ||
"sha224": 28, | ||
"sha256": 32, | ||
"sha384": 48, | ||
"sha512": 64, | ||
"sha3_224": 28, | ||
"sha3_256": 32, | ||
"sha3_384": 48, | ||
"sha3_512": 64, | ||
"sha512_224": 28, | ||
"sha512_256": 32, | ||
"shake_128": 0, # TODO | ||
"shake_256": 0, # TODO | ||
"sm3": 32, | ||
} | ||
|
||
HASHLIB_SIZES = { | ||
"hashlib.blake2s": 32, | ||
"hashlib.blake2b": 64, | ||
"hashlib.sha224": 28, | ||
"hashlib.sha256": 32, | ||
"hashlib.sha384": 48, | ||
"hashlib.sha512": 64, | ||
"hashlib.sha3_224": 28, | ||
"hashlib.sha3_256": 32, | ||
"hashlib.sha3_384": 48, | ||
"hashlib.sha3_512": 64, | ||
"hashlib.sha512_224": 28, | ||
"hashlib.sha512_256": 32, | ||
"hashlib.shake_128": 0, # TODO | ||
"hashlib.shake_256": 0, # TODO | ||
"hashlib.sm3": 32, | ||
} | ||
|
||
|
||
class HmacWeakKey(Rule): | ||
def __init__(self, id: str) -> None: | ||
super().__init__( | ||
id=id, | ||
name="insufficient_key_size", | ||
description=__doc__, | ||
cwe_id=326, | ||
message="The given key is only '{0}' bytes which is insufficient " | ||
"for the '{2}' algorithm.", | ||
wildcards={ | ||
"hashlib.*": [ | ||
"blake2s", | ||
"blake2b", | ||
"sha224", | ||
"sha256", | ||
"sha384", | ||
"sha512", | ||
"sha3_224", | ||
"sha3_256", | ||
"sha3_384", | ||
"sha3_512", | ||
"sha512_224", | ||
"sha512_256", | ||
"shake_128", | ||
"shake_256", | ||
"sm3", | ||
], | ||
"hmac.*": [ | ||
"new", | ||
"digest", | ||
], | ||
}, | ||
) | ||
|
||
def analyze_call(self, context: dict, call: Call) -> Result: | ||
if call.name_qualified not in ("hmac.new", "hmac.digest"): | ||
return | ||
|
||
# new(key, msg=None, digestmod='') | ||
# Create a new hashing object and return it. | ||
# | ||
# key: bytes or buffer, The starting key for the hash. | ||
# msg: bytes or buffer, Initial input for the hash, or None. | ||
# digestmod: A hash name suitable for hashlib.new(). *OR* | ||
# A hashlib constructor returning a new hash object. | ||
# *OR* | ||
# A module supporting PEP 247. | ||
# | ||
# Required as of 3.8, despite its position after the | ||
# optional | ||
# msg argument. Passing it as a keyword argument is | ||
# recommended, though not required for legacy API | ||
# reasons. | ||
# | ||
# You can now feed arbitrary bytes into the object using its | ||
# update() method, and can ask for the hash value at any time | ||
# by calling its digest() or hexdigest() methods. | ||
# | ||
# digest(key, msg, digest) | ||
# Fast inline implementation of HMAC. | ||
# | ||
# key: bytes or buffer, The key for the keyed hash object. | ||
# msg: bytes or buffer, Input message. | ||
# digest: A hash name suitable for hashlib.new() for best | ||
# performance. *OR* | ||
# A hashlib constructor returning a new hash object. | ||
# *OR* | ||
# A module supporting PEP 247. | ||
if call.name_qualified == "hmac.new": | ||
arg_name = "digestmod" | ||
else: | ||
arg_name = "digest" | ||
|
||
arg0 = call.get_argument(position=0, name="key") | ||
if arg0.value in ( | ||
"secrets.token_bytes", | ||
"secrets.token_hex", | ||
"secrets.token_urlsafe", | ||
): | ||
symbol = context["symtab"].get(arg0.node.text.decode()) | ||
lastcall = symbol.call_history[-1] | ||
nbytes = lastcall.get_argument(position=0, name="nbytes").value | ||
key_size = nbytes if nbytes is not None else 32 | ||
elif arg0.is_str: | ||
key_size = len(arg0.value_str) | ||
else: | ||
return | ||
|
||
arg2 = call.get_argument(position=2, name=arg_name) | ||
if arg2.value in HASHLIB_SIZES: | ||
digest = arg2.value | ||
min_digest_size = HASHLIB_SIZES.get(digest) | ||
elif arg2.is_str and arg2.value_str in HASH_NAME_SIZES: | ||
digest = arg2.value_str | ||
min_digest_size = HASH_NAME_SIZES.get(digest) | ||
else: | ||
return | ||
|
||
if key_size >= min_digest_size: | ||
return | ||
|
||
return Result( | ||
rule_id=self.id, | ||
location=Location(node=arg0.node), | ||
message=self.message.format(key_size, min_digest_size, digest), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_blake2b.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
# level: NONE | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes(64) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest="blake2b") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_hashlib_blake2b.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
# level: NONE | ||
import hashlib | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes(64) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest=hashlib.blake2b) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_hashlib_sha384.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
# level: NONE | ||
import hashlib | ||
import hmac | ||
from secrets import token_bytes | ||
|
||
|
||
key = b"my-secret-key" | ||
key = token_bytes(nbytes=48) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest=hashlib.sha384) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_hashlib_sha3_384.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
# level: NONE | ||
import hashlib | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes(nbytes=48) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest=hashlib.sha3_384) |
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_hashlib_sha3_512.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
# level: NONE | ||
import hashlib | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes(64) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest=hashlib.sha3_512) |
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_hashlib_sha512.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
# level: NONE | ||
import hashlib | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes(64) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest=hashlib.sha512) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_sha384.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
# level: NONE | ||
import hmac | ||
from secrets import token_bytes | ||
|
||
|
||
key = b"my-secret-key" | ||
key = token_bytes(nbytes=48) | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest="sha384") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
tests/unit/rules/python/stdlib/hmac/examples/hmac_digest_sha3_256.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
# level: NONE | ||
import hmac | ||
import secrets | ||
|
||
|
||
key = b"my-secret-key" | ||
key = secrets.token_bytes() | ||
message = b"Hello, world!" | ||
hmac.digest(key, message, digest="sha3_256") |
Oops, something went wrong.