Skip to content

Commit

Permalink
Check value of usedforsecurity for hashlib
Browse files Browse the repository at this point in the history
In Python 3.9+ hashlib has a new argument named usedforsecurity
to indicate whether the hash is intended to be used for security
or not. The default value is True. So a user must explicit set
to False to state their non-security use.

As a result of this chnage in Python, the severity has been
moved up to HIGH if the usedforsecurity is True. But on earlier
versions of Python, the severity will remain at MEDIUM since
we don't know the intent of usage.

https://docs.python.org/3/library/hashlib.html#hashlib.new

Closes #748

Signed-off-by: Eric Brown <browne@vmware.com>
  • Loading branch information
ericwb committed Feb 6, 2022
1 parent 1c407d4 commit 49d80d4
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
34 changes: 27 additions & 7 deletions bandit/plugins/hashlib_new_insecure_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
CWE information added
"""
import distutils
import sys

import bandit
from bandit.core import issue
from bandit.core import test_properties as test
Expand All @@ -55,10 +58,27 @@ def hashlib_new(context):
"sha",
"sha1",
):
return bandit.Issue(
severity=bandit.MEDIUM,
confidence=bandit.HIGH,
cwe=issue.Cwe.BROKEN_CRYPTO,
text="Use of insecure MD4 or MD5 hash function.",
lineno=context.node.lineno,
)
if sys.version_info >= (3, 9):
# Python 3.9 includes a usedforsecurity argument
usedforsecurity = (
args[2]
if len(args) > 2
else keywords.get("usedforsecurity", "True")
)

if distutils.util.strtobool(usedforsecurity):
return bandit.Issue(
severity=bandit.HIGH,
confidence=bandit.HIGH,
cwe=issue.Cwe.BROKEN_CRYPTO,
text="Use of insecure MD4 or MD5 hash function.",
lineno=context.node.lineno,
)
else:
return bandit.Issue(
severity=bandit.MEDIUM,
confidence=bandit.HIGH,
cwe=issue.Cwe.BROKEN_CRYPTO,
text="Use of insecure MD4 or MD5 hash function.",
lineno=context.node.lineno,
)
12 changes: 12 additions & 0 deletions examples/hashlib_new_insecure_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

hashlib.new(string='test', name='MD5')

# 3rd arg only availabe in Python 3.9+
hashlib.new('md5', b'test', True)

hashlib.new('sha1')

hashlib.new(string='test', name='SHA1')
Expand All @@ -18,7 +21,16 @@

hashlib.new(name='SHA', string='test')

# usedforsecurity arg only availabe in Python 3.9+
hashlib.new('sha1', usedforsecurity=True)

# Test that plugin does not flag valid hash functions.
hashlib.new('sha256')

hashlib.new('SHA512')

# 3rd arg only availabe in Python 3.9+
hashlib.new('md5', b'test', False)

# usedforsecurity arg only availabe in Python 3.9+
hashlib.new(name='sha1', usedforsecurity=False)
34 changes: 30 additions & 4 deletions tests/functional/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,10 +800,36 @@ def test_unverified_context(self):

def test_hashlib_new_insecure_functions(self):
"""Test insecure hash functions created by `hashlib.new`."""
expect = {
"SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 9, "HIGH": 0},
"CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 9},
}
if sys.version_info >= (3, 9):
expect = {
"SEVERITY": {
"UNDEFINED": 0,
"LOW": 0,
"MEDIUM": 0,
"HIGH": 11,
},
"CONFIDENCE": {
"UNDEFINED": 0,
"LOW": 0,
"MEDIUM": 0,
"HIGH": 11,
},
}
else:
expect = {
"SEVERITY": {
"UNDEFINED": 0,
"LOW": 0,
"MEDIUM": 13,
"HIGH": 0,
},
"CONFIDENCE": {
"UNDEFINED": 0,
"LOW": 0,
"MEDIUM": 0,
"HIGH": 13,
},
}
self.check_example("hashlib_new_insecure_functions.py", expect)

def test_blacklist_pycrypto(self):
Expand Down

0 comments on commit 49d80d4

Please sign in to comment.