Files
xiaoxia-saas/.venv-ci-root/Lib/site-packages/bandit/plugins/hashlib_insecure_functions.py
T

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)