Use sphinx autodoc to generate docs from docstring
Rather than having separate rst documentation files, this patch auto generates the docs from the docstrings in the modules. Should make it easier to maintain. Also renamed directory docs to doc to be consistent with all other OpenStack projects. Change-Id: Iaed77f8358ccb6edaf2627fbabdcc855272b4ea2
This commit is contained in:
parent
c9eb2c1321
commit
222c0809b3
|
@ -10,8 +10,8 @@ venv*
|
|||
build/*
|
||||
cover/*
|
||||
.coverage
|
||||
docs/build/*
|
||||
doc/build/*
|
||||
ChangeLog
|
||||
docs/source/api
|
||||
doc/source/api
|
||||
.*.sw?
|
||||
AUTHORS
|
||||
|
|
|
@ -14,6 +14,43 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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]_.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
.. [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
|
||||
|
||||
.. versionadded:: 0.15.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import checks
|
||||
|
||||
|
|
|
@ -14,6 +14,44 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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``
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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()
|
||||
|
||||
References
|
||||
----------
|
||||
- https://bugs.launchpad.net/juniperopenstack/+bug/1456193
|
||||
- https://bugs.launchpad.net/heat/+bug/1397883
|
||||
- https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement
|
||||
|
||||
.. versionadded:: 0.11.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -14,6 +14,76 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
A number of Python methods and functions are known to have potential security
|
||||
implications. The blacklist calls plugin test is designed to detect the use of
|
||||
these methods by scanning code for method calls and checking for their presence
|
||||
in a configurable blacklist. The scanned calls are fully qualified and
|
||||
de-aliased prior to checking. To illustrate this, imagine a check for
|
||||
"evil.thing()" running on the following example code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import evil as good
|
||||
|
||||
good.thing()
|
||||
thing()
|
||||
|
||||
This would generate a warning about calling `evil.thing()` despite the module
|
||||
being aliased as `good`. It would also not generate a warning on the call to
|
||||
`thing()` in the local module, as it's fully qualified name will not match.
|
||||
|
||||
Each of the provided blacklisted calls can be grouped such that they generate
|
||||
appropriate warnings (message, severity) and a token `{func}` may be used
|
||||
in the provided output message, to be replaced with the actual method name.
|
||||
|
||||
Due to the nature of the test, confidence is always reported as HIGH
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
blacklist_calls:
|
||||
bad_name_sets:
|
||||
- pickle:
|
||||
qualnames:
|
||||
- pickle.loads
|
||||
- pickle.load
|
||||
- pickle.Unpickler
|
||||
- cPickle.loads
|
||||
- cPickle.load
|
||||
- cPickle.Unpickler
|
||||
message: >
|
||||
Pickle library appears to be in use, possible security
|
||||
issue.
|
||||
- marshal:
|
||||
qualnames: [marshal.load, marshal.loads]
|
||||
message: >
|
||||
Deserialization with the {func} is possibly dangerous.
|
||||
level: LOW
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Pickle library appears to be in use, possible security issue.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/pickle_deserialize.py:20
|
||||
19 serialized = cPickle.dumps({(): []})
|
||||
20 print(cPickle.loads(serialized))
|
||||
21
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import fnmatch
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
@ -22,6 +21,89 @@ from bandit.core.test_properties import *
|
|||
@takes_config
|
||||
@checks('Import', 'ImportFrom')
|
||||
def blacklist_imports(context, config):
|
||||
"""blacklist_imports
|
||||
|
||||
A number of Python modules are known to provide collections of
|
||||
functionality with potential security implications. The blacklist imports
|
||||
plugin test is designed to detect the use of these modules by scanning code
|
||||
for `import` statements and checking for the imported modules presence in a
|
||||
configurable blacklist. The imported modules are fully qualified and
|
||||
de-aliased prior to checking. To illustrate this, imagine a check for
|
||||
"module.evil" running on the following example code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import module # no warning
|
||||
import module.evil # warning
|
||||
from module import evil # warning
|
||||
from module import evil as good # warning
|
||||
|
||||
This would generate a warning about importing `module.evil` in each of the
|
||||
last three cases, despite the module being aliased as `good` in one of
|
||||
them. It would also not generate a warning on the first import
|
||||
(of `module`) as it's fully qualified name will not match.
|
||||
|
||||
Each of the provided blacklisted modules can be grouped such that they
|
||||
generate appropriate warnings (message, severity) and a token `{module}`
|
||||
may be used in the provided output message, to be replaced with the actual
|
||||
module name.
|
||||
|
||||
Due to the nature of the test, confidence is always reported as HIGH
|
||||
|
||||
Config Options:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
blacklist_imports:
|
||||
bad_import_sets:
|
||||
- xml_libs:
|
||||
imports:
|
||||
- xml.etree.cElementTree
|
||||
- xml.etree.ElementTree
|
||||
- xml.sax.expatreader
|
||||
- xml.sax
|
||||
- xml.dom.expatbuilder
|
||||
- xml.dom.minidom
|
||||
- xml.dom.pulldom
|
||||
- lxml.etree
|
||||
- lxml
|
||||
message: >
|
||||
Using {module} to parse untrusted XML data is known to
|
||||
be vulnerable to XML attacks. Replace {module} with the
|
||||
equivalent defusedxml package.
|
||||
level: LOW
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Using xml.sax to parse untrusted XML data is known to be
|
||||
vulnerable to XML attacks. Replace xml.sax with the equivalent
|
||||
defusedxml package.
|
||||
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/xml_sax.py:1
|
||||
1 import xml.sax
|
||||
2 from xml import sax
|
||||
|
||||
>> Issue: Using xml.sax.parseString to parse untrusted XML data is
|
||||
known to be vulnerable to XML attacks. Replace xml.sax.parseString with
|
||||
its defusedxml equivalent function.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/xml_sax.py:21
|
||||
20 # bad
|
||||
21 xml.sax.parseString(xmlString, ExampleContentHandler())
|
||||
22 xml.sax.parse('notaxmlfilethatexists.xml', ExampleContentHandler())
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
|
||||
checks = _load_checks(config)
|
||||
|
||||
# for each check, go through and see if it matches all qualifications
|
||||
|
@ -36,6 +118,52 @@ def blacklist_imports(context, config):
|
|||
@takes_config('blacklist_imports')
|
||||
@checks('Call')
|
||||
def blacklist_import_func(context, config):
|
||||
"""blacklist_import_func
|
||||
|
||||
This test is in all ways identical blacklist_imports. However, it
|
||||
is designed to catch modules that have been imported using Python's special
|
||||
builtin import function, `__import__()`. For example, running a test on the
|
||||
following code for `module.evil` would warn as shown:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
__import__('module') # no warning
|
||||
__import__('module.evil') # warning
|
||||
|
||||
This test shares the configuration provided for the standard
|
||||
blacklist_imports test.
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Using xml.sax to parse untrusted XML data is known to be
|
||||
vulnerable to XML attacks. Replace xml.sax with the equivalent
|
||||
defusedxml package.
|
||||
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/xml_sax.py:1
|
||||
1 import xml.sax
|
||||
2 from xml import sax
|
||||
|
||||
>> Issue: Using xml.sax.parseString to parse untrusted XML data is
|
||||
known to be vulnerable to XML attacks. Replace xml.sax.parseString with
|
||||
its defusedxml equivalent function.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/xml_sax.py:21
|
||||
20 # bad
|
||||
21 xml.sax.parseString(xmlString, ExampleContentHandler())
|
||||
22 xml.sax.parse('notaxmlfilethatexists.xml', ExampleContentHandler())
|
||||
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
checks = _load_checks(config)
|
||||
if context.call_function_name_qual == '__import__':
|
||||
for check in checks:
|
||||
|
|
|
@ -14,6 +14,44 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
- https://security.openstack.org/guidelines/dg_validate-certificates.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -13,6 +13,35 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Use of exec detected.
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/exec-py2.py:2
|
||||
1 exec("do evil")
|
||||
2 exec "do evil"
|
||||
|
||||
References
|
||||
----------
|
||||
- https://docs.python.org/2.0/ref/exec.html
|
||||
- TODO: add info on exec and similar to sec best practice and link here
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
|
||||
import six
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -12,6 +12,56 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_rootwrap-recommendations-and-plans.html # noqa
|
||||
- https://security.openstack.org/guidelines/dg_use-oslo-rootwrap-securely.html
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -14,6 +14,51 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_apply-restrictive-file-permissions.html # noqa
|
||||
- https://en.wikipedia.org/wiki/File_system_permissions
|
||||
- https://security.openstack.org
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import stat
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -14,6 +14,38 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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))
|
||||
|
||||
References
|
||||
----------
|
||||
- __TODO__ : add best practice info on binding to all interfaces, and link
|
||||
here.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -14,6 +14,49 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
The use of hard-coded passwords increases the possibility of password guessing
|
||||
tremendously. This plugin test looks for all string literals and checks to see
|
||||
if they exist in a list of likely default passwords. If they are found in the
|
||||
list, a LOW severity issue is reported.
|
||||
|
||||
Note: this test is very noisy and likely to result in many false positives.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
This plugin test takes a similarly named config block, `hardcoded_password`.
|
||||
Here a path, `word_list`, can be given to indicate where the default password
|
||||
word list file may be found.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
hardcoded_password:
|
||||
# Support for full path, relative path and special "%(site_data_dir)s"
|
||||
# substitution (/usr/{local}/share)
|
||||
word_list: "%(site_data_dir)s/wordlist/default-passwords"
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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")
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/Use_of_hard-coded_password
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -14,6 +14,50 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
hardcoded_tmp_directory:
|
||||
tmp_dirs: ['/tmp', '/var/tmp', '/dev/shm']
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block: none
|
||||
|
||||
>> Issue: Probable insecure usage of temp file/directory.
|
||||
Severity: Medium Confidence: Medium
|
||||
Location: ./examples/hardcoded-tmp.py:1
|
||||
1 f = open('/tmp/abc', 'w')
|
||||
2 f.write('def')
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_using-temporary-files-securely.html # noqa
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -14,6 +14,53 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://github.com/paramiko/paramiko
|
||||
- https://www.owasp.org/index.php/Command_Injection
|
||||
|
||||
.. versionadded:: 0.12.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -50,6 +50,96 @@ def _evaluate_shell_call(context):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def subprocess_popen_with_shell_equals_true(context, config):
|
||||
"""subprocess_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:
|
||||
|
||||
- :doc:`../plugins/linux_commands_wildcard_injection`
|
||||
- :doc:`../plugins/subprocess_without_shell_equals_true`
|
||||
- :doc:`../plugins/start_process_with_no_shell`
|
||||
- :doc:`../plugins/start_process_with_a_shell`
|
||||
- :doc:`../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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
shell_injection:
|
||||
|
||||
# Start a process using the subprocess module, or one of its
|
||||
wrappers.
|
||||
subprocess:
|
||||
- subprocess.Popen
|
||||
- subprocess.call
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments # noqa
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
if config and context.call_function_name_qual in config['subprocess']:
|
||||
if context.check_call_arg_value('shell', 'True'):
|
||||
if len(context.call_args) > 0:
|
||||
|
@ -82,6 +172,71 @@ def subprocess_popen_with_shell_equals_true(context, config):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def subprocess_without_shell_equals_true(context, config):
|
||||
"""subprocess_without_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:
|
||||
|
||||
- :doc:`../plugins/linux_commands_wildcard_injection`
|
||||
- :doc:`../plugins/subprocess_popen_with_shell_equals_true`
|
||||
- :doc:`../plugins/start_process_with_no_shell`
|
||||
- :doc:`../plugins/start_process_with_a_shell`
|
||||
- :doc:`../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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
shell_injection:
|
||||
# Start a process using the subprocess module, or one of its
|
||||
wrappers.
|
||||
subprocess:
|
||||
- subprocess.Popen
|
||||
- subprocess.call
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments # noqa
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
if config and context.call_function_name_qual in config['subprocess']:
|
||||
if not context.check_call_arg_value('shell', 'True'):
|
||||
return bandit.Issue(
|
||||
|
@ -95,10 +250,73 @@ def subprocess_without_shell_equals_true(context, config):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def any_other_function_with_shell_equals_true(context, config):
|
||||
"""any_other_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:
|
||||
|
||||
- :doc:`../plugins/linux_commands_wildcard_injection`
|
||||
- :doc:`../plugins/subprocess_popen_with_shell_equals_true`
|
||||
- :doc:`../plugins/subprocess_without_shell_equals_true`
|
||||
- :doc:`../plugins/start_process_with_no_shell`
|
||||
- :doc:`../plugins/start_process_with_a_shell`
|
||||
- :doc:`../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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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]
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html # noqa
|
||||
"""
|
||||
'''Alerts on any function call that includes a shell=True parameter.
|
||||
|
||||
Multiple "helpers" with varying names have been identified across
|
||||
various OpenStack projects.
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
'''
|
||||
if config and context.call_function_name_qual not in config['subprocess']:
|
||||
if context.check_call_arg_value('shell', 'True'):
|
||||
|
@ -113,6 +331,75 @@ def any_other_function_with_shell_equals_true(context, config):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def start_process_with_a_shell(context, config):
|
||||
"""start_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 MEDIUM
|
||||
severity warning.
|
||||
|
||||
See also:
|
||||
|
||||
- :doc:`../plugins/linux_commands_wildcard_injection`
|
||||
- :doc:`../plugins/subprocess_without_shell_equals_true`
|
||||
- :doc:`../plugins/start_process_with_no_shell`
|
||||
- :doc:`../plugins/start_process_with_partial_path`
|
||||
- :doc:`../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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Starting a process with a shell: check for injection.
|
||||
Severity: Medium Confidence: Medium
|
||||
Location: examples/os_system.py:3
|
||||
2
|
||||
3 os.system('/bin/echo hi')
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#os.system
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments # noqa
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
"""
|
||||
if config and context.call_function_name_qual in config['shell']:
|
||||
if len(context.call_args) > 0:
|
||||
sev = _evaluate_shell_call(context)
|
||||
|
@ -144,6 +431,81 @@ def start_process_with_a_shell(context, config):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def start_process_with_no_shell(context, config):
|
||||
"""start_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:
|
||||
|
||||
- :doc:`../plugins/linux_commands_wildcard_injection`
|
||||
- :doc:`../plugins/subprocess_without_shell_equals_true`
|
||||
- :doc:`../plugins/start_process_with_a_shell`
|
||||
- :doc:`../plugins/start_process_with_partial_path`
|
||||
- :doc:`../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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#os.system
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments # noqa
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
"""
|
||||
|
||||
if config and context.call_function_name_qual in config['no_shell']:
|
||||
return bandit.Issue(
|
||||
severity=bandit.LOW,
|
||||
|
@ -155,6 +517,78 @@ def start_process_with_no_shell(context, config):
|
|||
@takes_config('shell_injection')
|
||||
@checks('Call')
|
||||
def start_process_with_partial_path(context, config):
|
||||
"""start_process_with_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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References:
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#process-management
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
"""
|
||||
|
||||
if config and len(context.call_args):
|
||||
if(context.call_function_name_qual in config['subprocess'] or
|
||||
context.call_function_name_qual in config['shell'] or
|
||||
|
|
|
@ -14,6 +14,53 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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 + ...
|
||||
|
||||
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)
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/SQL_Injection
|
||||
- https://security.openstack.org/guidelines/dg_parameterize-database-queries.html # noqa
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import ast
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -14,6 +14,96 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 *")
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://en.wikipedia.org/wiki/Wildcard_character
|
||||
- http://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -25,6 +25,83 @@ def get_bad_proto_versions(config):
|
|||
@takes_config
|
||||
@checks('Call')
|
||||
def ssl_with_bad_version(context, config):
|
||||
"""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:
|
||||
|
||||
- :doc:`../plugins/ssl_with_bad_defaults`
|
||||
- :doc:`../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`` and
|
||||
``OP_NO_SSLv3`` flags for this purpose.
|
||||
|
||||
|
||||
Config Options:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References:
|
||||
|
||||
- http://heartbleed.com/
|
||||
- https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
bad_ssl_versions = get_bad_proto_versions(config)
|
||||
if (context.call_function_name_qual == 'ssl.wrap_socket'):
|
||||
if context.check_call_arg_value('ssl_version', bad_ssl_versions):
|
||||
|
@ -58,6 +135,51 @@ def ssl_with_bad_version(context, config):
|
|||
@takes_config("ssl_with_bad_version")
|
||||
@checks('FunctionDef')
|
||||
def ssl_with_bad_defaults(context, config):
|
||||
"""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 :doc:`../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:
|
||||
|
||||
- :doc:`../plugins/ssl_with_bad_version`
|
||||
- :doc:`../plugins/ssl_with_no_version`
|
||||
|
||||
|
||||
Config Options:
|
||||
|
||||
This test shares the configuration provided for the standard
|
||||
:doc:`../plugins/ssl_with_bad_version` test, please refer to its
|
||||
documentation.
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References:
|
||||
|
||||
- http://heartbleed.com/
|
||||
- https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
|
||||
bad_ssl_versions = get_bad_proto_versions(config)
|
||||
for default in context.function_def_defaults_qual:
|
||||
val = default.split(".")[-1]
|
||||
|
@ -73,6 +195,51 @@ def ssl_with_bad_defaults(context, config):
|
|||
|
||||
@checks('Call')
|
||||
def ssl_with_no_version(context):
|
||||
"""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 :doc:`../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:
|
||||
|
||||
- :doc:`../plugins/ssl_with_bad_version`
|
||||
- :doc:`../plugins/ssl_with_bad_defaults`
|
||||
|
||||
|
||||
Config Options:
|
||||
|
||||
This test shares the configuration provided for the standard
|
||||
:doc:`../plugins/ssl_with_bad_version` test, please refer to its
|
||||
documentation.
|
||||
|
||||
Sample Output:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References:
|
||||
|
||||
- http://heartbleed.com/
|
||||
- https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
|
||||
.. versionadded:: 0.9.0
|
||||
"""
|
||||
if (context.call_function_name_qual == 'ssl.wrap_socket'):
|
||||
if context.check_call_arg_value('ssl_version') is None:
|
||||
# check_call_arg_value() returns False if the argument is found
|
||||
|
|
|
@ -14,6 +14,64 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 to mitigate XSS vulnerabilities.
|
||||
Severity: High Confidence: High
|
||||
Location: ./examples/jinja2_templating.py:15
|
||||
14
|
||||
15 Environment(loader=templateLoader,
|
||||
16 load=templateLoader)
|
||||
17
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
|
||||
- https://realpython.com/blog/python/primer-on-jinja-templating/
|
||||
- http://jinja.pocoo.org/docs/dev/api/#autoescaping
|
||||
- https://security.openstack.org
|
||||
- https://security.openstack.org/guidelines/dg_cross-site-scripting-xss.html
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
|
||||
"""
|
||||
|
||||
import ast
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -12,6 +12,47 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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")
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- http://www.makotemplates.org/
|
||||
- https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
|
||||
- https://security.openstack.org
|
||||
- https://security.openstack.org/guidelines/dg_cross-site-scripting-xss.html
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -12,6 +12,60 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
password_config_option_not_marked_secret:
|
||||
function_names:
|
||||
- oslo.config.cfg.StrOpt
|
||||
- oslo_config.cfg.StrOpt
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 identifed, 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',
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_protect-sensitive-data-in-files.html # noqa
|
||||
|
||||
.. versionadded:: 0.10.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
from bandit.core import constants
|
||||
|
|
|
@ -14,6 +14,70 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
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
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
do_some_stuff()
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
try_except_pass:
|
||||
check_typed_exception: True
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Try, Except, Pass detected.
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/try_except_pass.py:4
|
||||
3 a = 1
|
||||
4 except:
|
||||
5 pass
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
"""
|
||||
|
||||
import ast
|
||||
|
||||
import bandit
|
||||
|
|
|
@ -12,6 +12,40 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
Description
|
||||
-----------
|
||||
As computational power increases, so does the ability to break ciphers with
|
||||
smaller key lengths. The recommended key length size is 2048 and higher. 1024
|
||||
bits and below are now considered breakable. This plugin test checks for use
|
||||
of any key less than 2048 bits and returns a high severity error if lower than
|
||||
1024 and a medium severity error greater than 1024 but less than 2048.
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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,
|
||||
|
||||
References
|
||||
----------
|
||||
- http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf
|
||||
- https://security.openstack.org/guidelines/dg_strong-crypto.html
|
||||
|
||||
.. versionadded:: 0.14.0
|
||||
|
||||
"""
|
||||
|
||||
import bandit
|
||||
from bandit.core.test_properties import *
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ Getting Started
|
|||
:maxdepth: 1
|
||||
|
||||
config
|
||||
tests/index
|
||||
plugins/index
|
||||
formatters/index
|
||||
|
||||
Indices and tables
|
|
@ -0,0 +1,8 @@
|
|||
-----------------------------------------
|
||||
any_other_function_with_shell_equals_true
|
||||
-----------------------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: any_other_function_with_shell_equals_true
|
||||
:noindex:
|
|
@ -0,0 +1,5 @@
|
|||
-----------
|
||||
assert_used
|
||||
-----------
|
||||
|
||||
.. automodule:: bandit.plugins.asserts
|
|
@ -0,0 +1,5 @@
|
|||
---------------
|
||||
blacklist_calls
|
||||
---------------
|
||||
|
||||
.. automodule:: bandit.plugins.blacklist_calls
|
|
@ -0,0 +1,8 @@
|
|||
---------------------
|
||||
blacklist_import_func
|
||||
---------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.blacklist_imports
|
||||
|
||||
.. autofunction:: blacklist_import_func
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
-----------------
|
||||
blacklist_imports
|
||||
-----------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.blacklist_imports
|
||||
|
||||
.. autofunction:: blacklist_imports
|
||||
:noindex:
|
|
@ -0,0 +1,5 @@
|
|||
---------
|
||||
exec_used
|
||||
---------
|
||||
|
||||
.. automodule:: bandit.plugins.exec
|
|
@ -0,0 +1,5 @@
|
|||
------------------------------------
|
||||
execute_with_run_as_root_equals_true
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.exec_as_root
|
|
@ -0,0 +1,5 @@
|
|||
----------------
|
||||
flask_debug_true
|
||||
----------------
|
||||
|
||||
.. automodule:: bandit.plugins.app_debug
|
|
@ -0,0 +1,5 @@
|
|||
-----------------------------
|
||||
hardcoded_bind_all_interfaces
|
||||
-----------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.general_bind_all_interfaces
|
|
@ -0,0 +1,5 @@
|
|||
-------------------
|
||||
hardcoded_passwords
|
||||
-------------------
|
||||
|
||||
.. automodule:: bandit.plugins.general_hardcoded_password
|
|
@ -0,0 +1,5 @@
|
|||
-------------------------
|
||||
hardcoded_sql_expressions
|
||||
-------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.injection_sql
|
|
@ -0,0 +1,5 @@
|
|||
-----------------------
|
||||
hardcoded_tmp_directory
|
||||
-----------------------
|
||||
|
||||
.. automodule:: bandit.plugins.general_hardcoded_tmp
|
|
@ -0,0 +1,5 @@
|
|||
-----------------------
|
||||
jinja2_autoescape_false
|
||||
-----------------------
|
||||
|
||||
.. automodule:: bandit.plugins.jinja2_templates
|
|
@ -0,0 +1,5 @@
|
|||
---------------------------------
|
||||
linux_commands_wildcard_injection
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.injection_wildcard
|
|
@ -0,0 +1,5 @@
|
|||
--------------
|
||||
paramiko_calls
|
||||
--------------
|
||||
|
||||
.. automodule:: bandit.plugins.injection_paramiko
|
|
@ -0,0 +1,5 @@
|
|||
----------------------------------------
|
||||
password_config_option_not_marked_secret
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.secret_config_option
|
|
@ -0,0 +1,5 @@
|
|||
-------------------------------
|
||||
request_with_no_cert_validation
|
||||
-------------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.crypto_request_no_cert_validation
|
|
@ -0,0 +1,5 @@
|
|||
------------------------
|
||||
set_bad_file_permissions
|
||||
------------------------
|
||||
|
||||
.. automodule:: bandit.plugins.general_bad_file_permissions
|
|
@ -0,0 +1,8 @@
|
|||
---------------------
|
||||
ssl_with_bad_defaults
|
||||
---------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.insecure_ssl_tls
|
||||
|
||||
.. autofunction:: ssl_with_bad_version
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
--------------------
|
||||
ssl_with_bad_version
|
||||
--------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.insecure_ssl_tls
|
||||
|
||||
.. autofunction:: ssl_with_bad_defaults
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
-------------------
|
||||
ssl_with_no_version
|
||||
-------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.insecure_ssl_tls
|
||||
|
||||
.. autofunction:: ssl_with_no_version
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
--------------------------
|
||||
start_process_with_a_shell
|
||||
--------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: start_process_with_a_shell
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
---------------------------
|
||||
start_process_with_no_shell
|
||||
---------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: start_process_with_no_shell
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
-------------------------------
|
||||
start_process_with_partial_path
|
||||
-------------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: start_process_with_partial_path
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
---------------------------------------
|
||||
subprocess_popen_with_shell_equals_true
|
||||
---------------------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: subprocess_popen_with_shell_equals_true
|
||||
:noindex:
|
|
@ -0,0 +1,8 @@
|
|||
------------------------------------
|
||||
subprocess_without_shell_equals_true
|
||||
------------------------------------
|
||||
|
||||
.. currentmodule:: bandit.plugins.injection_shell
|
||||
|
||||
.. autofunction:: subprocess_without_shell_equals_true
|
||||
:noindex:
|
|
@ -0,0 +1,5 @@
|
|||
---------------
|
||||
try_except_pass
|
||||
---------------
|
||||
|
||||
.. automodule:: bandit.plugins.try_except_pass
|
|
@ -0,0 +1,5 @@
|
|||
---------------------
|
||||
use_of_mako_templates
|
||||
---------------------
|
||||
|
||||
.. automodule:: bandit.plugins.mako_templates
|
|
@ -0,0 +1,5 @@
|
|||
----------------------
|
||||
weak_cryptographic_key
|
||||
----------------------
|
||||
|
||||
.. automodule:: bandit.plugins.weak_cryptographic_key
|
|
@ -1,65 +0,0 @@
|
|||
any_other_function_with_shell_equals_true
|
||||
=========================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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:
|
||||
|
||||
- :doc:`linux_commands_wildcard_injection`.
|
||||
- :doc:`subprocess_popen_with_shell_equals_true`.
|
||||
- :doc:`subprocess_without_shell_equals_true`.
|
||||
- :doc:`start_process_with_no_shell`.
|
||||
- :doc:`start_process_with_a_shell`.
|
||||
- :doc:`start_process_with_partial_path`.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v 0.9.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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]
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
|
@ -1,38 +0,0 @@
|
|||
assert_used
|
||||
===========
|
||||
|
||||
Description
|
||||
-----------
|
||||
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#grammar-token-assert_stmt
|
||||
for more info on ``assert``
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.11.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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()
|
||||
|
||||
References
|
||||
----------
|
||||
- https://bugs.launchpad.net/juniperopenstack/+bug/1456193
|
||||
- https://bugs.launchpad.net/heat/+bug/1397883
|
||||
- https://docs.python.org/2/reference/simple_stmts.html#grammar-token-assert_stmt
|
|
@ -1,71 +0,0 @@
|
|||
|
||||
blacklist_calls
|
||||
===============
|
||||
|
||||
Description
|
||||
-----------
|
||||
A number of Python methods and functions are known to have potential security
|
||||
implications. The blacklist calls plugin test is designed to detect the use of
|
||||
these methods by scanning code for method calls and checking for their presence
|
||||
in a configurable blacklist. The scanned calls are fully qualified and
|
||||
de-aliased prior to checking. To illustrate this, imagine a check for
|
||||
"evil.thing()" running on the following example code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import evil as good
|
||||
|
||||
good.thing()
|
||||
thing()
|
||||
|
||||
This would generate a warning about calling `evil.thing()` despite the module
|
||||
being aliased as `good`. It would also not generate a warning on the call to
|
||||
`thing()` in the local module, as it's fully qualified name will not match.
|
||||
|
||||
Each of the provided blacklisted calls can be grouped such that they generate
|
||||
appropriate warnings (message, severity) and a token `{func}` may be used
|
||||
in the provided output message, to be replaced with the actual method name.
|
||||
|
||||
Due to the nature of the test, confidence is always reported as HIGH
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
blacklist_calls:
|
||||
bad_name_sets:
|
||||
- pickle:
|
||||
qualnames:
|
||||
- pickle.loads
|
||||
- pickle.load
|
||||
- pickle.Unpickler
|
||||
- cPickle.loads
|
||||
- cPickle.load
|
||||
- cPickle.Unpickler
|
||||
message: >
|
||||
Pickle library appears to be in use, possible security issue.
|
||||
- marshal:
|
||||
qualnames: [marshal.load, marshal.loads]
|
||||
message: >
|
||||
Deserialization with the {func} is possibly dangerous.
|
||||
level: LOW
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Pickle library appears to be in use, possible security issue.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/pickle_deserialize.py:20
|
||||
19 serialized = cPickle.dumps({(): []})
|
||||
20 print(cPickle.loads(serialized))
|
||||
21
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
|
@ -1,55 +0,0 @@
|
|||
|
||||
blacklist_import_func
|
||||
=====================
|
||||
Description
|
||||
-----------
|
||||
This test is in all ways identical to :doc:`blacklist_imports`. However, it
|
||||
is designed to catch modules that have been imported using Python's special
|
||||
builtin import function, `__import__()`. For example, running a test on the
|
||||
following code for `module.evil` would warn as shown:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
__import__('module') # no warning
|
||||
__import__('module.evil') # warning
|
||||
|
||||
Please see the documentation for :doc:`blacklist_imports` for more details.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
This test shares the configuration provided for the standard
|
||||
:doc:`blacklist_imports` test.
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Using xml.sax to parse untrusted XML data is known to be
|
||||
vulnerable to XML attacks. Replace xml.sax with the equivalent defusedxml
|
||||
package.
|
||||
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/xml_sax.py:1
|
||||
1 import xml.sax
|
||||
2 from xml import sax
|
||||
|
||||
>> Issue: Using xml.sax.parseString to parse untrusted XML data is known to
|
||||
be vulnerable to XML attacks. Replace xml.sax.parseString with its
|
||||
defusedxml equivalent function.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/xml_sax.py:21
|
||||
20 # bad
|
||||
21 xml.sax.parseString(xmlString, ExampleContentHandler())
|
||||
22 xml.sax.parse('notaxmlfilethatexists.xml', ExampleContentHandler())
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- :doc:`blacklist_imports`.
|
||||
- https://security.openstack.org
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
blacklist_imports
|
||||
=================
|
||||
|
||||
Description
|
||||
-----------
|
||||
A number of Python modules are known to provide collections of functionality
|
||||
with potential security implications. The blacklist imports plugin test is
|
||||
designed to detect the use of these modules by scanning code for `import`
|
||||
statements and checking for the imported modules presence in a configurable
|
||||
blacklist. The imported modules are fully qualified and de-aliased prior to
|
||||
checking. To illustrate this, imagine a check for "module.evil" running on the
|
||||
following example code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import module # no warning
|
||||
import module.evil # warning
|
||||
from module import evil # warning
|
||||
from module import evil as good # warning
|
||||
|
||||
This would generate a warning about importing `module.evil` in each of the last
|
||||
three cases, despite the module being aliased as `good` in one of them. It would
|
||||
also not generate a warning on the first import (of `module`) as it's fully
|
||||
qualified name will not match.
|
||||
|
||||
Each of the provided blacklisted modules can be grouped such that they generate
|
||||
appropriate warnings (message, severity) and a token `{module}` may be used
|
||||
in the provided output message, to be replaced with the actual module name.
|
||||
|
||||
Due to the nature of the test, confidence is always reported as HIGH
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
blacklist_imports:
|
||||
bad_import_sets:
|
||||
- xml_libs:
|
||||
imports:
|
||||
- xml.etree.cElementTree
|
||||
- xml.etree.ElementTree
|
||||
- xml.sax.expatreader
|
||||
- xml.sax
|
||||
- xml.dom.expatbuilder
|
||||
- xml.dom.minidom
|
||||
- xml.dom.pulldom
|
||||
- lxml.etree
|
||||
- lxml
|
||||
message: >
|
||||
Using {module} to parse untrusted XML data is known to be
|
||||
vulnerable to XML attacks. Replace {module} with the
|
||||
equivalent defusedxml package.
|
||||
level: LOW
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Using xml.sax to parse untrusted XML data is known to be
|
||||
vulnerable to XML attacks. Replace xml.sax with the equivalent defusedxml
|
||||
package.
|
||||
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/xml_sax.py:1
|
||||
1 import xml.sax
|
||||
2 from xml import sax
|
||||
|
||||
>> Issue: Using xml.sax.parseString to parse untrusted XML data is known to
|
||||
be vulnerable to XML attacks. Replace xml.sax.parseString with its
|
||||
defusedxml equivalent function.
|
||||
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/xml_sax.py:21
|
||||
20 # bad
|
||||
21 xml.sax.parseString(xmlString, ExampleContentHandler())
|
||||
22 xml.sax.parse('notaxmlfilethatexists.xml', ExampleContentHandler())
|
||||
|
||||
References
|
||||
----------
|
||||
- see also :doc:`blacklist_import_func`.
|
||||
- https://security.openstack.org
|
|
@ -1,32 +0,0 @@
|
|||
exec_used
|
||||
=========
|
||||
|
||||
Description
|
||||
-----------
|
||||
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:
|
||||
|
||||
- `This statement supports dynamic execution of Python code.` [1]_
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Use of exec detected.
|
||||
Severity: Medium Confidence: High
|
||||
Location: ./examples/exec-py2.py:2
|
||||
1 exec("do evil")
|
||||
2 exec "do evil"
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] https://docs.python.org/2.0/ref/exec.html
|
||||
.. [2] TODO : add info on exec and similar to sec best practice and link here
|
|
@ -1,51 +0,0 @@
|
|||
|
||||
execute_with_run_as_root_equals_true
|
||||
====================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_rootwrap-recommendations-and-plans.html
|
||||
- https://security.openstack.org/guidelines/dg_use-oslo-rootwrap-securely.html
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
flask_debug_true
|
||||
================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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]_.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.15.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
.. [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
|
|
@ -1,33 +0,0 @@
|
|||
|
||||
hardcoded_bind_all_interfaces
|
||||
=============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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))
|
||||
|
||||
References
|
||||
----------
|
||||
- __TODO__ : add best practice info on binding to all interfaces, and link here.
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
hardcoded_password
|
||||
==================
|
||||
|
||||
Description
|
||||
-----------
|
||||
The use of hard-coded passwords increases the possibility of password guessing
|
||||
tremendously. This plugin test looks for all string literals and checks to see
|
||||
if they exist in a list of likely default passwords. If they are found in the
|
||||
list, a LOW severity issue is reported.
|
||||
|
||||
Note: this test is very noisy and likely to result in many false positives.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
This plugin test takes a similarly named config block, `hardcoded_password`.
|
||||
Here a path, `word_list`, can be given to indicate where the default password
|
||||
word list file may be found.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
hardcoded_password:
|
||||
# Support for full path, relative path and special "%(site_data_dir)s"
|
||||
# substitution (/usr/{local}/share)
|
||||
word_list: "%(site_data_dir)s/wordlist/default-passwords"
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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")
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/Use_of_hard-coded_password
|
|
@ -1,48 +0,0 @@
|
|||
hardcoded_sql_expressions
|
||||
=========================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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 + ...
|
||||
|
||||
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)
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/SQL_Injection
|
||||
- https://security.openstack.org/guidelines/dg_parameterize-database-queries.html
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
hardcoded_tmp_directory
|
||||
=======================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
hardcoded_tmp_directory:
|
||||
tmp_dirs: ['/tmp', '/var/tmp', '/dev/shm']
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block: none
|
||||
|
||||
>> Issue: Probable insecure usage of temp file/directory.
|
||||
Severity: Medium Confidence: Medium
|
||||
Location: ./examples/hardcoded-tmp.py:1
|
||||
1 f = open('/tmp/abc', 'w')
|
||||
2 f.write('def')
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_using-temporary-files-securely.html
|
|
@ -1,59 +0,0 @@
|
|||
|
||||
jinja2_autoescape_false
|
||||
=======================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 to mitigate XSS vulnerabilities.
|
||||
Severity: High Confidence: High
|
||||
Location: ./examples/jinja2_templating.py:15
|
||||
14
|
||||
15 Environment(loader=templateLoader,
|
||||
16 load=templateLoader)
|
||||
17
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
|
||||
- https://realpython.com/blog/python/primer-on-jinja-templating/
|
||||
- http://jinja.pocoo.org/docs/dev/api/#autoescaping
|
||||
- https://security.openstack.org
|
||||
- https://security.openstack.org/guidelines/dg_cross-site-scripting-xss.html
|
|
@ -1,98 +0,0 @@
|
|||
|
||||
linux_commands_wildcard_injection
|
||||
=================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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. See also :doc:`start_process_with_partial_path` for related
|
||||
issues with partial paths.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
|
||||
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.
|
||||
|
||||
see also:
|
||||
|
||||
- :doc:`start_process_with_partial_path`
|
||||
- :doc:`start_process_with_a_shell`
|
||||
- :doc:`start_process_with_no_shell`
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 *")
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://en.wikipedia.org/wiki/Wildcard_character
|
||||
- http://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
paramiko_calls
|
||||
==============
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
See also:
|
||||
|
||||
- :doc:`start_process_with_a_shell`
|
||||
- :doc:`subprocess_popen_with_shell_equals_true`
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.12.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
- https://security.openstack.org
|
||||
- https://github.com/paramiko/paramiko
|
||||
- https://www.owasp.org/index.php/Command_Injection
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
password_config_option_not_marked_secret
|
||||
========================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
password_config_option_not_marked_secret:
|
||||
function_names:
|
||||
- oslo.config.cfg.StrOpt
|
||||
- oslo_config.cfg.StrOpt
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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 identifed, 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',
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_protect-sensitive-data-in-files.html
|
||||
- http://docs.openstack.org/developer/oslo.config/cfg.html#special-handling-instructions
|
|
@ -1,40 +0,0 @@
|
|||
|
||||
request_with_no_cert_validation
|
||||
===============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
- https://security.openstack.org/guidelines/dg_validate-certificates.html
|
|
@ -1,47 +0,0 @@
|
|||
|
||||
set_bad_file_permissions
|
||||
========================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org/guidelines/dg_apply-restrictive-file-permissions.html
|
||||
- https://en.wikipedia.org/wiki/File_system_permissions
|
||||
- https://security.openstack.org
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
ssl_with_bad_defaults
|
||||
=====================
|
||||
|
||||
Description
|
||||
-----------
|
||||
Several highly publicized [1]_ [2]_, 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 is part of a family of tests that detect the use of known bad
|
||||
versions of SSL/TLS, please see :doc:`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:
|
||||
|
||||
- :doc:`ssl_with_bad_version`.
|
||||
- :doc:`ssl_with_no_version`.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
This test shares the configuration provided for the standard
|
||||
:doc:`ssl_with_bad_version` test, please refer to it's
|
||||
:ref:`bad_ssl_config_options` documentation.
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- [1] http://heartbleed.com/
|
||||
- [2] https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
|
@ -1,83 +0,0 @@
|
|||
|
||||
ssl_with_bad_version
|
||||
====================
|
||||
|
||||
Description
|
||||
-----------
|
||||
Several highly publicized [1]_ [2]_, 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:
|
||||
|
||||
- :doc:`ssl_with_bad_defaults`.
|
||||
- :doc:`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`` and ``OP_NO_SSLv3``
|
||||
flags for this purpose.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
.. _bad_ssl_config_options:
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- [1] http://heartbleed.com/
|
||||
- [2] https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
|
||||
ssl_with_no_version
|
||||
===================
|
||||
|
||||
Description
|
||||
-----------
|
||||
Several highly publicized [1]_ [2]_, 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 is part of a family of tests that detect the use of known bad
|
||||
versions of SSL/TLS, please see :doc:`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:
|
||||
|
||||
- :doc:`ssl_with_bad_version`.
|
||||
- :doc:`ssl_with_bad_defaults`.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
This test shares the configuration provided for the standard
|
||||
:doc:`ssl_with_bad_version` test, please refer to it's
|
||||
:ref:`bad_ssl_config_options` documentation.
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- [1] http://heartbleed.com/
|
||||
- [2] https://poodlebleed.com/
|
||||
- https://security.openstack.org/
|
||||
- https://security.openstack.org/guidelines/dg_move-data-securely.html
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
|
||||
start_process_with_a_shell
|
||||
==============================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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 MEDIUM severity warning.
|
||||
|
||||
See also:
|
||||
|
||||
- :doc:`linux_commands_wildcard_injection`.
|
||||
- :doc:`subprocess_without_shell_equals_true`.
|
||||
- :doc:`start_process_with_no_shell`.
|
||||
- :doc:`start_process_with_partial_path`.
|
||||
- :doc:`subprocess_popen_with_shell_equals_true`.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Starting a process with a shell: check for injection.
|
||||
Severity: Medium Confidence: Medium
|
||||
Location: examples/os_system.py:3
|
||||
2
|
||||
3 os.system('/bin/echo hi')
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#os.system
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
|
@ -1,76 +0,0 @@
|
|||
|
||||
start_process_with_no_shell
|
||||
==============================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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:
|
||||
|
||||
- :doc:`linux_commands_wildcard_injection`.
|
||||
- :doc:`subprocess_without_shell_equals_true`.
|
||||
- :doc:`start_process_with_a_shell`.
|
||||
- :doc:`start_process_with_partial_path`.
|
||||
- :doc:`subprocess_popen_with_shell_equals_true`.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#os.system
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
|
@ -1,74 +0,0 @@
|
|||
|
||||
start_process_with_partial_path
|
||||
===============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.13.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
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
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/os.html#process-management
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
subprocess_popen_with_shell_equals_true
|
||||
=======================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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:
|
||||
|
||||
- :doc:`linux_commands_wildcard_injection`.
|
||||
- :doc:`subprocess_without_shell_equals_true`.
|
||||
- :doc:`start_process_with_no_shell`.
|
||||
- :doc:`start_process_with_a_shell`.
|
||||
- :doc:`start_process_with_partial_path`.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
shell_injection:
|
||||
|
||||
# Start a process using the subprocess module, or one of its wrappers.
|
||||
subprocess:
|
||||
- subprocess.Popen
|
||||
- subprocess.call
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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)
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
|
@ -1,68 +0,0 @@
|
|||
|
||||
subprocess_without_shell_equals_true
|
||||
==============================================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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:
|
||||
|
||||
- :doc:`linux_commands_wildcard_injection`.
|
||||
- :doc:`subprocess_popen_with_shell_equals_true`.
|
||||
- :doc:`start_process_with_no_shell`.
|
||||
- :doc:`start_process_with_a_shell`.
|
||||
- :doc:`start_process_with_partial_path`.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.9.0
|
||||
|
||||
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.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
shell_injection:
|
||||
# Start a process using the subprocess module, or one of its wrappers.
|
||||
subprocess:
|
||||
- subprocess.Popen
|
||||
- subprocess.call
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
||||
- https://docs.python.org/2/library/subprocess.html#frequently-used-arguments
|
||||
- https://security.openstack.org/guidelines/dg_avoid-shell-true.html
|
||||
- https://security.openstack.org/guidelines/dg_use-subprocess-securely.html
|
|
@ -1,66 +0,0 @@
|
|||
|
||||
try_except_pass
|
||||
===============
|
||||
|
||||
Description
|
||||
-----------
|
||||
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
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
do_some_stuff()
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.13.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
.. code-block:: yaml
|
||||
|
||||
try_except_pass:
|
||||
check_typed_exception: True
|
||||
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> Issue: Try, Except, Pass detected.
|
||||
Severity: Low Confidence: High
|
||||
Location: ./examples/try_except_pass.py:4
|
||||
3 a = 1
|
||||
4 except:
|
||||
5 pass
|
||||
|
||||
References
|
||||
----------
|
||||
- https://security.openstack.org
|
|
@ -1,47 +0,0 @@
|
|||
|
||||
use_of_mako_templates
|
||||
=====================
|
||||
|
||||
Description
|
||||
-----------
|
||||
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.
|
||||
|
||||
See also:
|
||||
|
||||
- :doc:`jinja2_autoescape_false`.
|
||||
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.10.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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")
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
- http://www.makotemplates.org/
|
||||
- https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
|
||||
- https://security.openstack.org
|
||||
- https://security.openstack.org/guidelines/dg_cross-site-scripting-xss.html
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
weak_cryptographic_key
|
||||
======================
|
||||
|
||||
Description
|
||||
-----------
|
||||
As computational power increases, so does the ability to break ciphers with
|
||||
smaller key lengths. The recommended key length size is 2048 and higher. 1024
|
||||
bits and below are now considered breakable. This plugin test checks for use
|
||||
of any key less than 2048 bits and returns a high severity error if lower than
|
||||
1024 and a medium severity error greater than 1024 but less than 2048.
|
||||
|
||||
Available Since
|
||||
---------------
|
||||
- Bandit v0.14.0
|
||||
|
||||
Config Options
|
||||
--------------
|
||||
None
|
||||
|
||||
Sample Output
|
||||
-------------
|
||||
.. code-block:: none
|
||||
|
||||
>> 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,
|
||||
|
||||
References
|
||||
----------
|
||||
- http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf
|
||||
- https://security.openstack.org/guidelines/dg_strong-crypto.html
|
Loading…
Reference in New Issue