122 lines
4.2 KiB
Python
122 lines
4.2 KiB
Python
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
r"""
|
|
======================================================================
|
|
B324: Test use of insecure md4, md5, or sha1 hash functions in hashlib
|
|
======================================================================
|
|
|
|
This plugin checks for the usage of the insecure MD4, MD5, or SHA1 hash
|
|
functions in ``hashlib`` and ``crypt``. The ``hashlib.new`` function provides
|
|
the ability to construct a new hashing object using the named algorithm. This
|
|
can be used to create insecure hash functions like MD4 and MD5 if they are
|
|
passed as algorithm names to this function.
|
|
|
|
This check does additional checking for usage of keyword usedforsecurity on all
|
|
function variations of hashlib.
|
|
|
|
Similar to ``hashlib``, this plugin also checks for usage of one of the
|
|
``crypt`` module's weak hashes. ``crypt`` also permits MD5 among other weak
|
|
hash variants.
|
|
|
|
:Example:
|
|
|
|
.. code-block:: none
|
|
|
|
>> Issue: [B324:hashlib] Use of weak MD4, MD5, or SHA1 hash for
|
|
security. Consider usedforsecurity=False
|
|
Severity: High Confidence: High
|
|
CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html)
|
|
Location: examples/hashlib_new_insecure_functions.py:3:0
|
|
More Info: https://bandit.readthedocs.io/en/latest/plugins/b324_hashlib.html
|
|
2
|
|
3 hashlib.new('md5')
|
|
4
|
|
|
|
.. seealso::
|
|
|
|
- https://cwe.mitre.org/data/definitions/327.html
|
|
|
|
.. versionadded:: 1.5.0
|
|
|
|
.. versionchanged:: 1.7.3
|
|
CWE information added
|
|
|
|
.. versionchanged:: 1.7.6
|
|
Added check for the crypt module weak hashes
|
|
|
|
""" # noqa: E501
|
|
import bandit
|
|
from bandit.core import issue
|
|
from bandit.core import test_properties as test
|
|
|
|
WEAK_HASHES = ("md4", "md5", "sha", "sha1")
|
|
WEAK_CRYPT_HASHES = ("METHOD_CRYPT", "METHOD_MD5", "METHOD_BLOWFISH")
|
|
|
|
|
|
def _hashlib_func(context, func):
|
|
keywords = context.call_keywords
|
|
|
|
if func in WEAK_HASHES:
|
|
if keywords.get("usedforsecurity", "True") == "True":
|
|
return bandit.Issue(
|
|
severity=bandit.HIGH,
|
|
confidence=bandit.HIGH,
|
|
cwe=issue.Cwe.BROKEN_CRYPTO,
|
|
text=f"Use of weak {func.upper()} hash for security. "
|
|
"Consider usedforsecurity=False",
|
|
lineno=context.node.lineno,
|
|
)
|
|
elif func == "new":
|
|
args = context.call_args
|
|
name = args[0] if args else keywords.get("name", None)
|
|
if isinstance(name, str) and name.lower() in WEAK_HASHES:
|
|
if keywords.get("usedforsecurity", "True") == "True":
|
|
return bandit.Issue(
|
|
severity=bandit.HIGH,
|
|
confidence=bandit.HIGH,
|
|
cwe=issue.Cwe.BROKEN_CRYPTO,
|
|
text=f"Use of weak {name.upper()} hash for "
|
|
"security. Consider usedforsecurity=False",
|
|
lineno=context.node.lineno,
|
|
)
|
|
|
|
|
|
def _crypt_crypt(context, func):
|
|
args = context.call_args
|
|
keywords = context.call_keywords
|
|
|
|
if func == "crypt":
|
|
name = args[1] if len(args) > 1 else keywords.get("salt", None)
|
|
if isinstance(name, str) and name in WEAK_CRYPT_HASHES:
|
|
return bandit.Issue(
|
|
severity=bandit.MEDIUM,
|
|
confidence=bandit.HIGH,
|
|
cwe=issue.Cwe.BROKEN_CRYPTO,
|
|
text=f"Use of insecure crypt.{name.upper()} hash function.",
|
|
lineno=context.node.lineno,
|
|
)
|
|
elif func == "mksalt":
|
|
name = args[0] if args else keywords.get("method", None)
|
|
if isinstance(name, str) and name in WEAK_CRYPT_HASHES:
|
|
return bandit.Issue(
|
|
severity=bandit.MEDIUM,
|
|
confidence=bandit.HIGH,
|
|
cwe=issue.Cwe.BROKEN_CRYPTO,
|
|
text=f"Use of insecure crypt.{name.upper()} hash function.",
|
|
lineno=context.node.lineno,
|
|
)
|
|
|
|
|
|
@test.test_id("B324")
|
|
@test.checks("Call")
|
|
def hashlib(context):
|
|
if isinstance(context.call_function_name_qual, str):
|
|
qualname_list = context.call_function_name_qual.split(".")
|
|
func = qualname_list[-1]
|
|
|
|
if "hashlib" in qualname_list:
|
|
return _hashlib_func(context, func)
|
|
|
|
elif "crypt" in qualname_list and func in ("crypt", "mksalt"):
|
|
return _crypt_crypt(context, func)
|