bandit.plugins package¶
Submodules¶
bandit.plugins.app_debug module¶
B201: Test for use of flask app with debug set to true¶
Running Flask applications in debug mode results in the Werkzeug debugger being enabled. This includes a feature that allows arbitrary code execution. Documentation for both Flask [1] and Werkzeug [2] strongly suggests that debug mode should never be enabled on production systems.
Operating a production server with debug mode enabled was the probable cause of the Patreon breach in 2015 [3].
Example: |
---|
>> Issue: A Flask app appears to be run with debug=True, which exposes
the Werkzeug debugger and allows the execution of arbitrary code.
Severity: High Confidence: High
Location: examples/flask_debug.py:10
9 #bad
10 app.run(debug=True)
11
See also
[1] | http://flask.pocoo.org/docs/0.10/quickstart/#debug-mode |
[2] | http://werkzeug.pocoo.org/docs/0.10/debug/ |
[3] | http://labs.detectify.com/post/130332638391/how-patreon-got-hacked-publicly-exposed-werkzeug # noqa |
New in version 0.15.0.
-
bandit.plugins.app_debug.
flask_debug_true
(context)¶
bandit.plugins.asserts module¶
B101: Test for use of assert¶
This plugin test checks for the use of the Python assert
keyword. It was
discovered that some projects used assert to enforce interface constraints.
However, assert is removed with compiling to optimised byte code (python -o
producing *.pyo files). This caused various protections to be removed. The use
of assert is also considered as general bad practice in OpenStack codebases.
Please see
https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement for
more info on assert
Example: |
---|
>> Issue: Use of assert detected. The enclosed code will be removed when
compiling to optimised byte code.
Severity: Low Confidence: High
Location: ./examples/assert.py:1
1 assert logged_in
2 display_assets()
See also
New in version 0.11.0.
-
bandit.plugins.asserts.
assert_used
(context)¶
bandit.plugins.crypto_request_no_cert_validation module¶
B501: Test for missing certificate validation¶
Encryption in general is typically critical to the security of many applications. Using TLS can greatly increase security by guaranteeing the identity of the party you are communicating with. This is accomplished by one or both parties presenting trusted certificates during the connection initialization phase of TLS.
When request methods are used certificates are validated automatically which is the desired behavior. If certificate validation is explicitly turned off Bandit will return a HIGH severity error.
Example: |
---|
>> Issue: [request_with_no_cert_validation] Requests call with verify=False
disabling SSL certificate checks, security issue.
Severity: High Confidence: High
Location: examples/requests-ssl-verify-disabled.py:4
3 requests.get('https://gmail.com', verify=True)
4 requests.get('https://gmail.com', verify=False)
5 requests.post('https://gmail.com', verify=True)
See also
New in version 0.9.0.
-
bandit.plugins.crypto_request_no_cert_validation.
request_with_no_cert_validation
(context)¶
bandit.plugins.exec module¶
B102: Test for the use of exec¶
This plugin test checks for the use of Python’s exec method or keyword. The Python docs succinctly describe why the use of exec is risky.
Example: |
---|
>> Issue: Use of exec detected.
Severity: Medium Confidence: High
Location: ./examples/exec-py2.py:2
1 exec("do evil")
2 exec "do evil"
See also
- https://docs.python.org/2.0/ref/exec.html
- TODO: add info on exec and similar to sec best practice and link here
New in version 0.9.0.
-
bandit.plugins.exec.
exec_issue
()¶
-
bandit.plugins.exec.
exec_used
(context)¶
bandit.plugins.exec_as_root module¶
B111: Test for the use of rootwrap running as root¶
Running commands as root dramatically increase their potential risk. Running commands with restricted user privileges provides defense in depth against command injection attacks, or developer and configuration error. This plugin test checks for specific methods being called with a keyword parameter run_as_root set to True, a common OpenStack idiom.
Config Options:
This test plugin takes a similarly named configuration block, execute_with_run_as_root_equals_true, providing a list, function_names, of function names. A call to any of these named functions will be checked for a run_as_root keyword parameter, and if True, will report a Low severity issue.
execute_with_run_as_root_equals_true:
function_names:
- ceilometer.utils.execute
- cinder.utils.execute
- neutron.agent.linux.utils.execute
- nova.utils.execute
- nova.utils.trycmd
Example: |
---|
>> Issue: Execute with run_as_root=True identified, possible security
issue.
Severity: Low Confidence: Medium
Location: ./examples/exec-as-root.py:26
25 nova_utils.trycmd('gcc --version')
26 nova_utils.trycmd('gcc --version', run_as_root=True)
27
See also
New in version 0.10.0.
-
bandit.plugins.exec_as_root.
execute_with_run_as_root_equals_true
(context, config)¶
-
bandit.plugins.exec_as_root.
gen_config
(name)¶
bandit.plugins.general_bad_file_permissions module¶
B103: Test for setting permissive file permissions¶
POSIX based operating systems utilize a permissions model to protect access to
parts of the file system. This model supports three roles “owner”, “group”
and “world” each role may have a combination of “read”, “write” or “execute”
flags sets. Python provides chmod
to manipulate POSIX style permissions.
This plugin test looks for the use of chmod
and will alert when it is used
to set particularly permissive control flags. A MEDIUM warning is generated if
a file is set to group executable and a HIGH warning is reported if a file is
set world writable. Warnings are given with HIGH confidence.
Example: |
---|
>> Issue: Probable insecure usage of temp file/directory.
Severity: Medium Confidence: Medium
Location: ./examples/os-chmod-py2.py:15
14 os.chmod('/etc/hosts', 0o777)
15 os.chmod('/tmp/oh_hai', 0x1ff)
16 os.chmod('/etc/passwd', stat.S_IRWXU)
>> Issue: Chmod setting a permissive mask 0777 on file (key_file).
Severity: High Confidence: High
Location: ./examples/os-chmod-py2.py:17
16 os.chmod('/etc/passwd', stat.S_IRWXU)
17 os.chmod(key_file, 0o777)
18
See also
New in version 0.9.0.
-
bandit.plugins.general_bad_file_permissions.
set_bad_file_permissions
(context)¶
bandit.plugins.general_bind_all_interfaces module¶
B104: Test for binding to all interfaces¶
Binding to all network interfaces can potentially open up a service to traffic on unintended interfaces, that may not be properly documented or secured. This plugin test looks for a string pattern “0.0.0.0” that may indicate a hardcoded binding to all network interfaces.
Example: |
---|
>> Issue: Possible binding to all interfaces.
Severity: Medium Confidence: Medium
Location: ./examples/binding.py:4
3 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4 s.bind(('0.0.0.0', 31137))
5 s.bind(('192.168.0.1', 8080))
See also
- __TODO__ : add best practice info on binding to all interfaces, and link here.
New in version 0.9.0.
-
bandit.plugins.general_bind_all_interfaces.
hardcoded_bind_all_interfaces
(context)¶
bandit.plugins.general_hardcoded_password module¶
-
bandit.plugins.general_hardcoded_password.
hardcoded_password_default
(context)¶ B107: Test for use of hard-coded password argument defaults
The use of hard-coded passwords increases the possibility of password guessing tremendously. This plugin test looks for all function definitions that specify a default string literal for some argument. It checks that the argument does not look like a password.
Variables are considered to look like a password if they have match any one of:
- “password”
- “pass”
- “passwd”
- “pwd”
- “secret”
- “token”
- “secrete”
Note: this can be noisy and may generate false positives.
Config Options:
None
Example: >> Issue: [B107:hardcoded_password_default] Possible hardcoded password: 'Admin' Severity: Low Confidence: Medium Location: ./examples/hardcoded-passwords.py:1 1 def someFunction(user, password="Admin"): 2 print("Hi " + user)
New in version 0.9.0.
-
bandit.plugins.general_hardcoded_password.
hardcoded_password_funcarg
(context)¶ B106: Test for use of hard-coded password function arguments
The use of hard-coded passwords increases the possibility of password guessing tremendously. This plugin test looks for all function calls being passed a keyword argument that is a string literal. It checks that the assigned local variable does not look like a password.
Variables are considered to look like a password if they have match any one of:
- “password”
- “pass”
- “passwd”
- “pwd”
- “secret”
- “token”
- “secrete”
Note: this can be noisy and may generate false positives.
Config Options:
None
Example: >> Issue: [B106:hardcoded_password_funcarg] Possible hardcoded password: 'blerg' Severity: Low Confidence: Medium Location: ./examples/hardcoded-passwords.py:16 15 16 doLogin(password="blerg")
New in version 0.9.0.
-
bandit.plugins.general_hardcoded_password.
hardcoded_password_string
(context)¶ B105: Test for use of hard-coded password strings
The use of hard-coded passwords increases the possibility of password guessing tremendously. This plugin test looks for all string literals and checks the following conditions:
- assigned to a variable that looks like a password
- assigned to a dict key that looks like a password
- used in a comparison with a variable that looks like a password
Variables are considered to look like a password if they have match any one of:
- “password”
- “pass”
- “passwd”
- “pwd”
- “secret”
- “token”
- “secrete”
Note: this can be noisy and may generate false positives.
Config Options:
None
Example: >> Issue: Possible hardcoded password '(root)' Severity: Low Confidence: Low Location: ./examples/hardcoded-passwords.py:5 4 def someFunction2(password): 5 if password == "root": 6 print("OK, logged in")
New in version 0.9.0.
bandit.plugins.general_hardcoded_tmp module¶
B108: Test for insecure usage of tmp file/directory¶
Safely creating a temporary file or directory means following a number of rules (see the references for more details). This plugin test looks for strings starting with (configurable) commonly used temporary paths, for example:
- /tmp
- /var/tmp
- /dev/shm
- etc
Config Options:
This test plugin takes a similarly named config block, hardcoded_tmp_directory. The config block provides a Python list, tmp_dirs, that lists string fragments indicating possible temporary file paths. Any string starting with one of these fragments will report a MEDIUM confidence issue.
hardcoded_tmp_directory:
tmp_dirs: ['/tmp', '/var/tmp', '/dev/shm']
Example: |
---|
New in version 0.9.0.
-
bandit.plugins.general_hardcoded_tmp.
gen_config
(name)¶
-
bandit.plugins.general_hardcoded_tmp.
hardcoded_tmp_directory
(context, config)¶
bandit.plugins.hashlib_new_insecure_functions module¶
B324: Test for use of insecure md4 and md5 hash functions in hashlib.new()¶
This plugin checks for the usage of the insecure MD4 and MD5 hash functions
in hashlib.new
function. 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 is similar to B303 blacklist check, except that this checks for insecure
hash functions created using hashlib.new
function.
Example: |
2 3 md5_hash = hashlib.new(‘md5’, string=’test’) 4 print(md5_hash) |
---|
New in version 1.5.0.
-
bandit.plugins.hashlib_new_insecure_functions.
hashlib_new
(context)¶
bandit.plugins.injection_paramiko module¶
B601: Test for shell injection within Paramiko¶
Paramiko is a Python library designed to work with the SSH2 protocol for secure (encrypted and authenticated) connections to remote machines. It is intended to run commands on a remote host. These commands are run within a shell on the target and are thus vulnerable to various shell injection attacks. Bandit reports a MEDIUM issue when it detects the use of Paramiko’s “exec_command” or “invoke_shell” methods advising the user to check inputs are correctly sanitized.
Example: |
---|
>> Issue: Possible shell injection via Paramiko call, check inputs are
properly sanitized.
Severity: Medium Confidence: Medium
Location: ./examples/paramiko_injection.py:4
3 # this is not safe
4 paramiko.exec_command('something; reallly; unsafe')
5
>> Issue: Possible shell injection via Paramiko call, check inputs are
properly sanitized.
Severity: Medium Confidence: Medium
Location: ./examples/paramiko_injection.py:10
9 # this is not safe
10 SSHClient.invoke_shell('something; bad; here\n')
11
See also
New in version 0.12.0.
-
bandit.plugins.injection_paramiko.
paramiko_calls
(context)¶
bandit.plugins.injection_shell module¶
-
bandit.plugins.injection_shell.
any_other_function_with_shell_equals_true
(context, config)¶ B604: Test for any function with shell equals true
Python possesses many mechanisms to invoke an external executable. However, doing so may present a security issue if appropriate care is not taken to sanitize any user provided or variable input.
This plugin test is part of a family of tests built to check for process spawning and warn appropriately. Specifically, this plugin test interrogates method calls for the presence of a keyword parameter shell equalling true. It is related to detection of shell injection issues and is intended to catch custom wrappers to vulnerable methods that may have been created.
See also:
- ../plugins/linux_commands_wildcard_injection
- ../plugins/subprocess_popen_with_shell_equals_true
- ../plugins/subprocess_without_shell_equals_true
- ../plugins/start_process_with_no_shell
- ../plugins/start_process_with_a_shell
- ../plugins/start_process_with_partial_path
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
Specifically, this plugin excludes those functions listed under the subprocess section, these methods are tested in a separate specific test plugin and this exclusion prevents duplicate issue reporting.
shell_injection: # Start a process using the subprocess module, or one of its wrappers. subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, utils.execute, utils.execute_with_timeout]
Example: >> Issue: Function call with shell=True parameter identified, possible security issue. Severity: Medium Confidence: High Location: ./examples/subprocess_shell.py:9 8 pop('/bin/gcc --version', shell=True) 9 Popen('/bin/gcc --version', shell=True) 10
See also
New in version 0.9.0.
-
bandit.plugins.injection_shell.
gen_config
(name)¶
-
bandit.plugins.injection_shell.
start_process_with_a_shell
(context, config)¶ B605: Test for starting a process with a shell
Python possesses many mechanisms to invoke an external executable. However, doing so may present a security issue if appropriate care is not taken to sanitize any user provided or variable input.
This plugin test is part of a family of tests built to check for process spawning and warn appropriately. Specifically, this test looks for the spawning of a subprocess using a command shell. This type of subprocess invocation is dangerous as it is vulnerable to various shell injection attacks. Great care should be taken to sanitize all input in order to mitigate this risk. Calls of this type are identified by the use of certain commands which are known to use shells. Bandit will report a LOW severity warning.
See also:
- ../plugins/linux_commands_wildcard_injection
- ../plugins/subprocess_without_shell_equals_true
- ../plugins/start_process_with_no_shell
- ../plugins/start_process_with_partial_path
- ../plugins/subprocess_popen_with_shell_equals_true
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This plugin specifically scans for methods listed in shell section.
shell_injection: shell: - os.system - os.popen - os.popen2 - os.popen3 - os.popen4 - popen2.popen2 - popen2.popen3 - popen2.popen4 - popen2.Popen3 - popen2.Popen4 - commands.getoutput - commands.getstatusoutput
Example: >> Issue: Starting a process with a shell: check for injection. Severity: Low Confidence: Medium Location: examples/os_system.py:3 2 3 os.system('/bin/echo hi')
See also
New in version 0.10.0.
-
bandit.plugins.injection_shell.
start_process_with_no_shell
(context, config)¶ B606: Test for starting a process with no shell
Python possesses many mechanisms to invoke an external executable. However, doing so may present a security issue if appropriate care is not taken to sanitize any user provided or variable input.
This plugin test is part of a family of tests built to check for process spawning and warn appropriately. Specifically, this test looks for the spawning of a subprocess in a way that doesn’t use a shell. Although this is generally safe, it maybe useful for penetration testing workflows to track where external system calls are used. As such a LOW severity message is generated.
See also:
- ../plugins/linux_commands_wildcard_injection
- ../plugins/subprocess_without_shell_equals_true
- ../plugins/start_process_with_a_shell
- ../plugins/start_process_with_partial_path
- ../plugins/subprocess_popen_with_shell_equals_true
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This plugin specifically scans for methods listed in no_shell section.
shell_injection: no_shell: - os.execl - os.execle - os.execlp - os.execlpe - os.execv - os.execve - os.execvp - os.execvpe - os.spawnl - os.spawnle - os.spawnlp - os.spawnlpe - os.spawnv - os.spawnve - os.spawnvp - os.spawnvpe - os.startfile
Example: >> Issue: [start_process_with_no_shell] Starting a process without a shell. Severity: Low Confidence: Medium Location: examples/os-spawn.py:8 7 os.spawnv(mode, path, args) 8 os.spawnve(mode, path, args, env) 9 os.spawnvp(mode, file, args)
See also
New in version 0.10.0.
-
bandit.plugins.injection_shell.
start_process_with_partial_path
(context, config)¶ B607: Test for starting a process with a partial path
Python possesses many mechanisms to invoke an external executable. If the desired executable path is not fully qualified relative to the filesystem root then this may present a potential security risk.
In POSIX environments, the PATH environment variable is used to specify a set of standard locations that will be searched for the first matching named executable. While convenient, this behavior may allow a malicious actor to exert control over a system. If they are able to adjust the contents of the PATH variable, or manipulate the file system, then a bogus executable may be discovered in place of the desired one. This executable will be invoked with the user privileges of the Python process that spawned it, potentially a highly privileged user.
This test will scan the parameters of all configured Python methods, looking for paths that do not start at the filesystem root, that is, do not have a leading ‘/’ character.
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This test will scan parameters of all methods in all sections. Note that methods are fully qualified and de-aliased prior to checking.
shell_injection: # Start a process using the subprocess module, or one of its wrappers. subprocess: - subprocess.Popen - subprocess.call # Start a process with a function vulnerable to shell injection. shell: - os.system - os.popen - popen2.Popen3 - popen2.Popen4 - commands.getoutput - commands.getstatusoutput # Start a process with a function that is not vulnerable to shell injection. no_shell: - os.execl - os.execle
Example: >> Issue: Starting a process with a partial executable path Severity: Low Confidence: High Location: ./examples/partial_path_process.py:3 2 from subprocess import Popen as pop 3 pop('gcc --version', shell=False)
See also
New in version 0.13.0.
-
bandit.plugins.injection_shell.
subprocess_popen_with_shell_equals_true
(context, config)¶ B602: Test for use of popen with shell equals true
Python possesses many mechanisms to invoke an external executable. However, doing so may present a security issue if appropriate care is not taken to sanitize any user provided or variable input.
This plugin test is part of a family of tests built to check for process spawning and warn appropriately. Specifically, this test looks for the spawning of a subprocess using a command shell. This type of subprocess invocation is dangerous as it is vulnerable to various shell injection attacks. Great care should be taken to sanitize all input in order to mitigate this risk. Calls of this type are identified by a parameter of ‘shell=True’ being given.
Additionally, this plugin scans the command string given and adjusts its reported severity based on how it is presented. If the command string is a simple static string containing no special shell characters, then the resulting issue has low severity. If the string is static, but contains shell formatting characters or wildcards, then the reported issue is medium. Finally, if the string is computed using Python’s string manipulation or formatting operations, then the reported issue has high severity. These severity levels reflect the likelihood that the code is vulnerable to injection.
See also:
- ../plugins/linux_commands_wildcard_injection
- ../plugins/subprocess_without_shell_equals_true
- ../plugins/start_process_with_no_shell
- ../plugins/start_process_with_a_shell
- ../plugins/start_process_with_partial_path
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This plugin specifically scans for methods listed in subprocess section that have shell=True specified.
shell_injection: # Start a process using the subprocess module, or one of its wrappers. subprocess: - subprocess.Popen - subprocess.call
Example: >> Issue: subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell Severity: Low Confidence: High Location: ./examples/subprocess_shell.py:21 20 subprocess.check_call(['/bin/ls', '-l'], shell=False) 21 subprocess.check_call('/bin/ls -l', shell=True) 22 >> Issue: call with shell=True contains special shell characters, consider moving extra logic into Python code Severity: Medium Confidence: High Location: ./examples/subprocess_shell.py:26 25 26 subprocess.Popen('/bin/ls *', shell=True) 27 subprocess.Popen('/bin/ls %s' % ('something',), shell=True) >> Issue: subprocess call with shell=True identified, security issue. Severity: High Confidence: High Location: ./examples/subprocess_shell.py:27 26 subprocess.Popen('/bin/ls *', shell=True) 27 subprocess.Popen('/bin/ls %s' % ('something',), shell=True) 28 subprocess.Popen('/bin/ls {}'.format('something'), shell=True)
See also
New in version 0.9.0.
-
bandit.plugins.injection_shell.
subprocess_without_shell_equals_true
(context, config)¶ B603: Test for use of subprocess with shell equals true
Python possesses many mechanisms to invoke an external executable. However, doing so may present a security issue if appropriate care is not taken to sanitize any user provided or variable input.
This plugin test is part of a family of tests built to check for process spawning and warn appropriately. Specifically, this test looks for the spawning of a subprocess without the use of a command shell. This type of subprocess invocation is not vulnerable to shell injection attacks, but care should still be taken to ensure validity of input.
Because this is a lesser issue than that described in subprocess_popen_with_shell_equals_true a LOW severity warning is reported.
See also:
- ../plugins/linux_commands_wildcard_injection
- ../plugins/subprocess_popen_with_shell_equals_true
- ../plugins/start_process_with_no_shell
- ../plugins/start_process_with_a_shell
- ../plugins/start_process_with_partial_path
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This plugin specifically scans for methods listed in subprocess section that have shell=False specified.
shell_injection: # Start a process using the subprocess module, or one of its wrappers. subprocess: - subprocess.Popen - subprocess.call
Example: >> Issue: subprocess call - check for execution of untrusted input. Severity: Low Confidence: High Location: ./examples/subprocess_shell.py:23 22 23 subprocess.check_output(['/bin/ls', '-l']) 24
See also
New in version 0.9.0.
bandit.plugins.injection_sql module¶
B608: Test for SQL injection¶
An SQL injection attack consists of insertion or “injection” of a SQL query via the input data given to an application. It is a very common attack vector. This plugin test looks for strings that resemble SQL statements that are involved in some form of string building operation. For example:
- “SELECT %s FROM derp;” % var
- “SELECT thing FROM ” + tab
- “SELECT ” + val + ” FROM ” + tab + …
- “SELECT {} FROM derp;”.format(var)
Unless care is taken to sanitize and control the input data when building such SQL statement strings, an injection attack becomes possible. If strings of this nature are discovered, a LOW confidence issue is reported. In order to boost result confidence, this plugin test will also check to see if the discovered string is in use with standard Python DBAPI calls execute or executemany. If so, a MEDIUM issue is reported. For example:
- cursor.execute(“SELECT %s FROM derp;” % var)
Example: |
---|
>> Issue: Possible SQL injection vector through string-based query
construction.
Severity: Medium Confidence: Low
Location: ./examples/sql_statements_without_sql_alchemy.py:4
3 query = "DELETE FROM foo WHERE id = '%s'" % identifier
4 query = "UPDATE foo SET value = 'b' WHERE id = '%s'" % identifier
5
See also
New in version 0.9.0.
-
bandit.plugins.injection_sql.
hardcoded_sql_expressions
(context)¶
bandit.plugins.injection_wildcard module¶
B609: Test for use of wildcard injection¶
Python provides a number of methods that emulate the behavior of standard Linux command line utilities. Like their Linux counterparts, these commands may take a wildcard “*” character in place of a file system path. This is interpreted to mean “any and all files or folders” and can be used to build partially qualified paths, such as “/home/user/*”.
The use of partially qualified paths may result in unintended consequences if an unexpected file or symlink is placed into the path location given. This becomes particularly dangerous when combined with commands used to manipulate file permissions or copy data off of a system.
This test plugin looks for usage of the following commands in conjunction with wild card parameters:
- ‘chown’
- ‘chmod’
- ‘tar’
- ‘rsync’
As well as any method configured in the shell or subprocess injection test configurations.
Config Options:
This plugin test shares a configuration with others in the same family, namely shell_injection. This configuration is divided up into three sections, subprocess, shell and no_shell. They each list Python calls that spawn subprocesses, invoke commands within a shell, or invoke commands without a shell (by replacing the calling process) respectively.
This test will scan parameters of all methods in all sections. Note that methods are fully qualified and de-aliased prior to checking.
shell_injection:
# Start a process using the subprocess module, or one of its wrappers.
subprocess:
- subprocess.Popen
- subprocess.call
# Start a process with a function vulnerable to shell injection.
shell:
- os.system
- os.popen
- popen2.Popen3
- popen2.Popen4
- commands.getoutput
- commands.getstatusoutput
# Start a process with a function that is not vulnerable to shell
injection.
no_shell:
- os.execl
- os.execle
Example: |
---|
>> Issue: Possible wildcard injection in call: subprocess.Popen
Severity: High Confidence: Medium
Location: ./examples/wildcard-injection.py:8
7 o.popen2('/bin/chmod *')
8 subp.Popen('/bin/chown *', shell=True)
9
>> Issue: subprocess call - check for execution of untrusted input.
Severity: Low Confidence: High
Location: ./examples/wildcard-injection.py:11
10 # Not vulnerable to wildcard injection
11 subp.Popen('/bin/rsync *')
12 subp.Popen("/bin/chmod *")
See also
New in version 0.9.0.
-
bandit.plugins.injection_wildcard.
linux_commands_wildcard_injection
(context, config)¶
bandit.plugins.insecure_ssl_tls module¶
-
bandit.plugins.insecure_ssl_tls.
gen_config
(name)¶
-
bandit.plugins.insecure_ssl_tls.
get_bad_proto_versions
(config)¶
-
bandit.plugins.insecure_ssl_tls.
ssl_with_bad_defaults
(context, config)¶ B503: Test for SSL use with bad defaults specified
This plugin is part of a family of tests that detect the use of known bad versions of SSL/TLS, please see ../plugins/ssl_with_bad_version for a complete discussion. Specifically, this plugin test scans for Python methods with default parameter values that specify the use of broken SSL/TLS protocol versions. Currently, detection supports methods using Python’s native SSL/TLS support and the pyOpenSSL module. A MEDIUM severity warning will be reported whenever known broken protocol versions are detected.
See also:
- ../plugins/ssl_with_bad_version
- ../plugins/ssl_with_no_version
Config Options:
This test shares the configuration provided for the standard ../plugins/ssl_with_bad_version test, please refer to its documentation.
Example: >> Issue: Function definition identified with insecure SSL/TLS protocol version by default, possible security issue. Severity: Medium Confidence: Medium Location: ./examples/ssl-insecure-version.py:28 27 28 def open_ssl_socket(version=SSL.SSLv2_METHOD): 29 pass
See also
New in version 0.9.0.
-
bandit.plugins.insecure_ssl_tls.
ssl_with_bad_version
(context, config)¶ B502: Test for SSL use with bad version used
Several highly publicized exploitable flaws have been discovered in all versions of SSL and early versions of TLS. It is strongly recommended that use of the following known broken protocol versions be avoided:
- SSL v2
- SSL v3
- TLS v1
- TLS v1.1
This plugin test scans for calls to Python methods with parameters that indicate the used broken SSL/TLS protocol versions. Currently, detection supports methods using Python’s native SSL/TLS support and the pyOpenSSL module. A HIGH severity warning will be reported whenever known broken protocol versions are detected.
It is worth noting that native support for TLS 1.2 is only available in more recent Python versions, specifically 2.7.9 and up, and 3.x
See also:
- ../plugins/ssl_with_bad_defaults
- ../plugins/ssl_with_no_version
A note on ‘SSLv23’:
Amongst the available SSL/TLS versions provided by Python/pyOpenSSL there exists the option to use SSLv23. This very poorly named option actually means “use the highest version of SSL/TLS supported by both the server and client”. This may (and should be) a version well in advance of SSL v2 or v3. Bandit can scan for the use of SSLv23 if desired, but its detection does not necessarily indicate a problem.
When using SSLv23 it is important to also provide flags to explicitly exclude bad versions of SSL/TLS from the protocol versions considered. Both the Python native and pyOpenSSL modules provide the
OP_NO_SSLv2
andOP_NO_SSLv3
flags for this purpose.Config Options:
ssl_with_bad_version: bad_protocol_versions: - PROTOCOL_SSLv2 - SSLv2_METHOD - SSLv23_METHOD - PROTOCOL_SSLv3 # strict option - PROTOCOL_TLSv1 # strict option - SSLv3_METHOD # strict option - TLSv1_METHOD # strict option
Example: >> Issue: ssl.wrap_socket call with insecure SSL/TLS protocol version identified, security issue. Severity: High Confidence: High Location: ./examples/ssl-insecure-version.py:13 12 # strict tests 13 ssl.wrap_socket(ssl_version=ssl.PROTOCOL_SSLv3) 14 ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLSv1)
See also
New in version 0.9.0.
-
bandit.plugins.insecure_ssl_tls.
ssl_with_no_version
(context)¶ B504: Test for SSL use with no version specified
This plugin is part of a family of tests that detect the use of known bad versions of SSL/TLS, please see ../plugins/ssl_with_bad_version for a complete discussion. Specifically, This plugin test scans for specific methods in Python’s native SSL/TLS support and the pyOpenSSL module that configure the version of SSL/TLS protocol to use. These methods are known to provide default value that maximize compatibility, but permit use of the aforementioned broken protocol versions. A LOW severity warning will be reported whenever this is detected.
See also:
- ../plugins/ssl_with_bad_version
- ../plugins/ssl_with_bad_defaults
Config Options:
This test shares the configuration provided for the standard ../plugins/ssl_with_bad_version test, please refer to its documentation.
Example: >> Issue: ssl.wrap_socket call with no SSL/TLS protocol version specified, the default SSLv23 could be insecure, possible security issue. Severity: Low Confidence: Medium Location: ./examples/ssl-insecure-version.py:23 22 23 ssl.wrap_socket() 24
See also
New in version 0.9.0.
bandit.plugins.jinja2_templates module¶
B701: Test for not auto escaping in jinja2¶
Jinja2 is a Python HTML templating system. It is typically used to build web applications, though appears in other places well, notably the Ansible automation system. When configuring the Jinja2 environment, the option to use autoescaping on input can be specified. When autoescaping is enabled, Jinja2 will filter input strings to escape any HTML content submitted via template variables. Without escaping HTML input the application becomes vulnerable to Cross Site Scripting (XSS) attacks.
Unfortunately, autoescaping is False by default. Thus this plugin test will warn on omission of an autoescape setting, as well as an explicit setting of false. A HIGH severity warning is generated in either of these scenarios.
Example: |
---|
>> Issue: Using jinja2 templates with autoescape=False is dangerous and can
lead to XSS. Use autoescape=True to mitigate XSS vulnerabilities.
Severity: High Confidence: High
Location: ./examples/jinja2_templating.py:11
10 templateEnv = jinja2.Environment(autoescape=False,
loader=templateLoader)
11 Environment(loader=templateLoader,
12 load=templateLoader,
13 autoescape=False)
14
>> Issue: By default, jinja2 sets autoescape to False. Consider using
autoescape=True or use the select_autoescape function to mitigate XSS
vulnerabilities.
Severity: High Confidence: High
Location: ./examples/jinja2_templating.py:15
14
15 Environment(loader=templateLoader,
16 load=templateLoader)
17
18 Environment(autoescape=select_autoescape(['html', 'htm', 'xml']),
19 loader=templateLoader)
See also
New in version 0.10.0.
-
bandit.plugins.jinja2_templates.
jinja2_autoescape_false
(context)¶
bandit.plugins.mako_templates module¶
B702: Test for use of mako templates¶
Mako is a Python templating system often used to build web applications. It is the default templating system used in Pylons and Pyramid. Unlike Jinja2 (an alternative templating system), Mako has no environment wide variable escaping mechanism. Because of this, all input variables must be carefully escaped before use to prevent possible vulnerabilities to Cross Site Scripting (XSS) attacks.
Example: |
---|
>> Issue: Mako templates allow HTML/JS rendering by default and are
inherently open to XSS attacks. Ensure variables in all templates are
properly sanitized via the 'n', 'h' or 'x' flags (depending on context).
For example, to HTML escape the variable 'data' do ${ data |h }.
Severity: Medium Confidence: High
Location: ./examples/mako_templating.py:10
9
10 mako.template.Template("hern")
11 template.Template("hern")
See also
New in version 0.10.0.
-
bandit.plugins.mako_templates.
use_of_mako_templates
(context)¶
bandit.plugins.secret_config_option module¶
B109: Test for a password based config option not marked secret¶
Passwords are sensitive and must be protected appropriately. In OpenStack Oslo there is an option to mark options “secret” which will ensure that they are not logged. This plugin detects usages of oslo configuration functions that appear to deal with strings ending in ‘password’ and flag usages where they have not been marked secret.
If such a value is found a MEDIUM severity error is generated. If ‘False’ or ‘None’ are explicitly set, Bandit will return a MEDIUM confidence issue. If Bandit can’t determine the value of secret it will return a LOW confidence issue.
Config Options:
password_config_option_not_marked_secret:
function_names:
- oslo.config.cfg.StrOpt
- oslo_config.cfg.StrOpt
Example: |
---|
>> Issue: [password_config_option_not_marked_secret] oslo config option
possibly not marked secret=True identified.
Severity: Medium Confidence: Low
Location: examples/secret-config-option.py:12
11 help="User's password"),
12 cfg.StrOpt('nova_password',
13 secret=secret,
14 help="Nova user password"),
15 ]
>> Issue: [password_config_option_not_marked_secret] oslo config option not
marked secret=True identified, security issue.
Severity: Medium Confidence: Medium
Location: examples/secret-config-option.py:21
20 help="LDAP ubind ser name"),
21 cfg.StrOpt('ldap_password',
22 help="LDAP bind user password"),
23 cfg.StrOpt('ldap_password_attribute',
New in version 0.10.0.
-
bandit.plugins.secret_config_option.
gen_config
(name)¶
-
bandit.plugins.secret_config_option.
password_config_option_not_marked_secret
(context, config)¶
bandit.plugins.try_except_continue module¶
B112: Test for a continue in the except block¶
Errors in Python code bases are typically communicated using Exceptions
.
An exception object is ‘raised’ in the event of an error and can be ‘caught’ at
a later point in the program, typically some error handling or logging action
will then be performed.
However, it is possible to catch an exception and silently ignore it while in a loop. This is illustrated with the following example
while keep_going:
try:
do_some_stuff()
except Exception:
continue
This pattern is considered bad practice in general, but also represents a potential security issue. A larger than normal volume of errors from a service can indicate an attempt is being made to disrupt or interfere with it. Thus errors should, at the very least, be logged.
There are rare situations where it is desirable to suppress errors, but this is
typically done with specific exception types, rather than the base Exception
class (or no type). To accommodate this, the test may be configured to ignore
‘try, except, continue’ where the exception is typed. For example, the
following would not generate a warning if the configuration option
checked_typed_exception
is set to False:
while keep_going:
try:
do_some_stuff()
except ZeroDivisionError:
continue
Config Options:
try_except_continue:
check_typed_exception: True
Example: |
---|
>> Issue: Try, Except, Continue detected.
Severity: Low Confidence: High
Location: ./examples/try_except_continue.py:5
4 a = i
5 except:
6 continue
See also
New in version 1.0.0.
-
bandit.plugins.try_except_continue.
gen_config
(name)¶
-
bandit.plugins.try_except_continue.
try_except_continue
(context, config)¶
bandit.plugins.try_except_pass module¶
B110: Test for a pass in the except block¶
Errors in Python code bases are typically communicated using Exceptions
.
An exception object is ‘raised’ in the event of an error and can be ‘caught’ at
a later point in the program, typically some error handling or logging action
will then be performed.
However, it is possible to catch an exception and silently ignore it. This is illustrated with the following example
try:
do_some_stuff()
except Exception:
pass
This pattern is considered bad practice in general, but also represents a potential security issue. A larger than normal volume of errors from a service can indicate an attempt is being made to disrupt or interfere with it. Thus errors should, at the very least, be logged.
There are rare situations where it is desirable to suppress errors, but this is
typically done with specific exception types, rather than the base Exception
class (or no type). To accommodate this, the test may be configured to ignore
‘try, except, pass’ where the exception is typed. For example, the following
would not generate a warning if the configuration option
checked_typed_exception
is set to False:
try:
do_some_stuff()
except ZeroDivisionError:
pass
Config Options:
try_except_pass:
check_typed_exception: True
Example: |
---|
>> Issue: Try, Except, Pass detected.
Severity: Low Confidence: High
Location: ./examples/try_except_pass.py:4
3 a = 1
4 except:
5 pass
See also
New in version 0.13.0.
-
bandit.plugins.try_except_pass.
gen_config
(name)¶
-
bandit.plugins.try_except_pass.
try_except_pass
(context, config)¶
bandit.plugins.weak_cryptographic_key module¶
B505: Test for weak cryptographic key use¶
As computational power increases, so does the ability to break ciphers with smaller key lengths. The recommended key length size for RSA and DSA algorithms is 2048 and higher. 1024 bits and below are now considered breakable. EC key length sizes are recommended to be 224 and higher with 160 and below considered breakable. This plugin test checks for use of any key less than those limits and returns a high severity error if lower than the lower threshold and a medium severity error for those lower than the higher threshold.
Example: |
---|
>> Issue: DSA key sizes below 1024 bits are considered breakable.
Severity: High Confidence: High
Location: examples/weak_cryptographic_key_sizes.py:36
35 # Also incorrect: without keyword args
36 dsa.generate_private_key(512,
37 backends.default_backend())
38 rsa.generate_private_key(3,
See also
New in version 0.14.0.
-
bandit.plugins.weak_cryptographic_key.
gen_config
(name)¶
-
bandit.plugins.weak_cryptographic_key.
weak_cryptographic_key
(context, config)¶
bandit.plugins.yaml_load module¶
B506: Test for use of yaml load¶
This plugin test checks for the unsafe usage of the yaml.load
function from
the PyYAML package. The yaml.load function provides the ability to construct
an arbitrary Python object, which may be dangerous if you receive a YAML
document from an untrusted source. The function yaml.safe_load limits this
ability to simple Python objects like integers or lists.
Please see
http://pyyaml.org/wiki/PyYAMLDocumentation#LoadingYAML for more information
on yaml.load
and yaml.safe_load
Example: |
4 ystr = yaml.dump({‘a’ : 1, ‘b’ : 2, ‘c’ : 3}) 5 y = yaml.load(ystr) 6 yaml.dump(y) |
---|
New in version 1.0.0.
-
bandit.plugins.yaml_load.
yaml_load
(context)¶