diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py index 8cfbe9de..df7015bb 100644 --- a/bandit/blacklists/calls.py +++ b/bandit/blacklists/calls.py @@ -14,6 +14,254 @@ # License for the specific language governing permissions and limitations # under the License. +r""" +==================================================== +Blacklist various Python calls known to be dangerous +==================================================== + +This balcklist data checks for a number of Python calls known to have possible +security implications. The following blacklist tests are run against any +function calls encoutered in the scanned code base, triggered by encoutering +ast.Call nodes. + +B301: pickle +------------ + +Pickle library appears to be in use, possible security issue. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B301 | pickle | - pickle.loads | Medium | +| | | - pickle.load | | +| | | - pickle.Unpickler | | +| | | - cPickle.loads | | +| | | - cPickle.load | | +| | | - cPickle.Unpickler | | ++------+---------------------+------------------------------------+-----------+ + +B302: marshal +------------- + +Deserialization with the marshal module is possibly dangerous. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B302 | marshal | - marshal.load | Medium | +| | | - marshal.loads | | ++------+---------------------+------------------------------------+-----------+ + +B303: md5 +--------- + +Use of insecure MD2, MD4, or MD5 hash function. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B303 | md5 | - hashlib.md5 | Medium | +| | | - Crypto.Hash.MD2.new | | +| | | - Crypto.Hash.MD4.new | | +| | | - Crypto.Hash.MD5.new | | +| | | - cryptography.hazmat.primitives | | +| | | .hashes.MD5 | | ++------+---------------------+------------------------------------+-----------+ + +B304 - B305: ciphers and modes +------------------------------ + +Use of insecure cipher or cipher mode. Replace with a known secure cipher such +as AES. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B304 | ciphers | - Crypto.Cipher.ARC2.new | High | +| | | - Crypto.Cipher.ARC4.new | | +| | | - Crypto.Cipher.Blowfish.new | | +| | | - Crypto.Cipher.DES.new | | +| | | - Crypto.Cipher.XOR.new | | +| | | - cryptography.hazmat.primitives | | +| | | .ciphers.algorithms.ARC4 | | +| | | - cryptography.hazmat.primitives | | +| | | .ciphers.algorithms.Blowfish | | +| | | - cryptography.hazmat.primitives | | +| | | .ciphers.algorithms.IDEA | | ++------+---------------------+------------------------------------+-----------+ +| B305 | cipher_modes | - cryptography.hazmat.primitives | Medium | +| | | .ciphers.modes.ECB | | ++------+---------------------+------------------------------------+-----------+ + +B306: mktemp_q +-------------- + +Use of insecure and deprecated function (mktemp). + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B306 | mktemp_q | - tempfile.mktemp | Medium | ++------+---------------------+------------------------------------+-----------+ + +B307: eval +---------- + +Use of possibly insecure function - consider using safer ast.literal_eval. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B307 | eval | - eval | Medium | ++------+---------------------+------------------------------------+-----------+ + +B308: mark_safe +--------------- + +Use of mark_safe() may expose cross-site scripting vulnerabilities and should +be reviewed. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B308 | mark_safe | - mark_safe | Medium | ++------+---------------------+------------------------------------+-----------+ + +B309: httpsconnection +--------------------- + +Use of HTTPSConnection does not provide security, see +https://wiki.openstack.org/wiki/OSSN/OSSN-0033 + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B309 | httpsconnection | - mark_safe | Medium | +| | | - httplib.HTTPSConnection | | +| | | - http.client.HTTPSConnection | | +| | | - six.moves.http_client | | +| | | .HTTPSConnection | | ++------+---------------------+------------------------------------+-----------+ + +B310: urllib_urlopen +-------------------- + +Audit url open for permitted schemes. Allowing use of 'file:'' or custom +schemes is often unexpected. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B310 | urllib_urlopen | - urllib.urlopen | Medium | +| | | - urllib.request.urlopen | | +| | | - urllib.urlretrieve | | +| | | - urllib.request.urlretrieve | | +| | | - urllib.URLopener | | +| | | - urllib.request.URLopener | | +| | | - urllib.FancyURLopener | | +| | | - urllib.request.FancyURLopener | | +| | | - urllib2.urlopen | | +| | | - urllib2.Reques | | +| | | - six.moves.urllib.request.urlopen | | +| | | - six.moves.urllib.request | | +| | | .urlretrieve | | +| | | - six.moves.urllib.request | | +| | | .URLopener | | +| | | - six.moves.urllib.request | | +| | | .FancyURLopener | | ++------+---------------------+------------------------------------+-----------+ + +B311: random +------------ + +Standard pseudo-random generators are not suitable for security/cryptographic +purposes. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B311 | random | - random.random | Low | +| | | - random.randrange | | +| | | - random.randint | | +| | | - random.choice | | +| | | - random.uniform | | +| | | - random.triangular | | ++------+---------------------+------------------------------------+-----------+ + +B312: telnetlib +--------------- + +Telnet-related funtions are being called. Telnet is considered insecure. Use +SSH or some other encrypted protocol. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B312 | telnetlib | - telnetlib.\* | High | ++------+---------------------+------------------------------------+-----------+ + +B313 - B320: XML +---------------- + +Most of this is based off of Christian Heimes' work on defusedxml: +https://pypi.python.org/pypi/defusedxml/#defusedxml-sax + +Using various XLM methods to parse untrusted XML data is known to be vulnerable +to XML attacks. Methods should be replaced with their defusedxml equivalents. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B313 | xml_bad_cElementTree| - xml.etree.cElementTree.parse | Medium | +| | | - xml.etree.cElementTree.iterparse | | +| | | - xml.etree.cElementTree.fromstring| | +| | | - xml.etree.cElementTree.XMLParser | | ++------+---------------------+------------------------------------+-----------+ +| B314 | xml_bad_ElementTree | - xml.etree.ElementTree.parse | Medium | +| | | - xml.etree.ElementTree.iterparse | | +| | | - xml.etree.ElementTree.fromstring | | +| | | - xml.etree.ElementTree.XMLParser | | ++------+---------------------+------------------------------------+-----------+ +| B315 | xml_bad_expatreader | - xml.sax.expatreader.create_parser| Medium | ++------+---------------------+------------------------------------+-----------+ +| B316 | xml_bad_expatbuilder| - xml.dom.expatbuilder.parse | Medium | +| | | - xml.dom.expatbuilder.parseString | | ++------+---------------------+------------------------------------+-----------+ +| B317 | xml_bad_sax | - xml.sax.parse | Medium | +| | | - xml.sax.parseString | | +| | | - xml.sax.make_parser | | ++------+---------------------+------------------------------------+-----------+ +| B318 | xml_bad_minidom | - xml.dom.minidom.parse | Medium | +| | | - xml.dom.minidom.parseString | | ++------+---------------------+------------------------------------+-----------+ +| B319 | xml_bad_pulldom | - xml.dom.pulldom.parse | Medium | +| | | - xml.dom.pulldom.parseString | | ++------+---------------------+------------------------------------+-----------+ +| B319 | xml_bad_pulldom | - xml.dom.pulldom.parse | Medium | +| | | - xml.dom.pulldom.parseString | | ++------+---------------------+------------------------------------+-----------+ +| B320 | xml_bad_etree | - lxml.etree.parse | Medium | +| | | - lxml.etree.fromstring | | +| | | - lxml.etree.RestrictedElement | | +| | | - lxml.etree.GlobalParserTLS | | +| | | - lxml.etree.getDefaultParser | | +| | | - lxml.etree.check_docinfo | | ++------+---------------------+------------------------------------+-----------+ + +B321: ftplib +------------ + +FTP-related funtions are being called. FTP is considered insecure. Use +SSH/SFTP/SCP or some other encrypted protocol. + ++------+---------------------+------------------------------------+-----------+ +| ID | Name | Calls | Severity | ++======+=====================+====================================+===========+ +| B321 | ftplib | - ftplib.\* | High | ++------+---------------------+------------------------------------+-----------+ + +""" + from bandit.blacklists import utils diff --git a/bandit/core/blacklisting.py b/bandit/core/blacklisting.py index 1b134809..6dd9e4ad 100644 --- a/bandit/core/blacklisting.py +++ b/bandit/core/blacklisting.py @@ -28,6 +28,15 @@ def report_issue(check, name): def blacklist(context, config): + """Generic blacklist test, B001. + + This generic blacklist test will be called for any encountered node with + defined blacklist data available. This data is loaded via plugins using + the 'bandit.blacklists' entry point. Please see the documentation for more + details. Each blacklist datum has a unique bandit ID that may be used for + filtering purposes, or alternatively all blacklisting can be filtered using + the id of this built in test, 'B001'. + """ blacklists = config node_type = context.node.__class__.__name__ diff --git a/doc/source/plugins/blacklist_calls.rst b/doc/source/blacklists/blacklist_calls.rst similarity index 51% rename from doc/source/plugins/blacklist_calls.rst rename to doc/source/blacklists/blacklist_calls.rst index 4c69869f..0897b6d3 100644 --- a/doc/source/plugins/blacklist_calls.rst +++ b/doc/source/blacklists/blacklist_calls.rst @@ -2,4 +2,4 @@ blacklist_calls --------------- -.. automodule:: bandit.plugins.blacklist_calls +.. automodule:: bandit.blacklists.calls diff --git a/doc/source/blacklists/blacklist_imports.rst b/doc/source/blacklists/blacklist_imports.rst new file mode 100644 index 00000000..3242cf88 --- /dev/null +++ b/doc/source/blacklists/blacklist_imports.rst @@ -0,0 +1,5 @@ +----------------- +blacklist_imports +----------------- + +.. automodule:: bandit.blacklists.imports diff --git a/doc/source/blacklists/index.rst b/doc/source/blacklists/index.rst new file mode 100644 index 00000000..cc5e5b80 --- /dev/null +++ b/doc/source/blacklists/index.rst @@ -0,0 +1,69 @@ +Bandit Blacklist Plugins +======================== + +Bandit supports built in functionality to implement blacklisting of imports and +function calls, this functionality is provided by built in test 'B001'. This +test may be filtered as per normal plugin filtering rules. + +The exact calls and imports that are blacklisted, and the issues reported, are +controlled by plugin methods with the entry point 'bandit.blacklists' and can +be extended by third party plugins if desired. Blacklist plugins will be +discovered by Bandit at startup and called. The returned results are combined +into the final data set, subject to Bandit's normal test include/exclude rules +allowing for fine grained control over blacklisted items. By convention, +blacklisted calls should have IDs in the B3xx range and imports should have IDs +in the B4xx range. + +Plugin functions should return a dictionary mapping AST node types to +lists of blacklist data. Currently the following node types are supported: + +- Call, used for blacklisting calls. +- Import, used for blacklisting module imports (this also implicitly tests + ImportFrom and Call nodes where the invoked function is Pythons built in + '__import__()' method). + +Items in the data lists are Python dictionaries with the following structure: + ++-------------+----------------------------------------------------+ +| key | data meaning | ++=============+====================================================+ +| 'name' | The issue name string. | ++-------------+----------------------------------------------------+ +| 'id' | The bandit ID of the check, this must be unique | +| | and is used for filtering blacklist checks. | ++-------------+----------------------------------------------------+ +| 'qualnames' | A Python list of fully qualified name strings. | ++-------------+----------------------------------------------------+ +| 'message' | The issue message reported, this is a string that | +| | may contain the token '{name}' that will be | +| | substituted with the matched qualname in the final | +| | report. | ++-------------+----------------------------------------------------+ +| 'level' | The severity level reported. | ++-------------+----------------------------------------------------+ + +A utility method bandit.blacklists.utils.build_conf_dict is provided to aid +building these dictionaries. + +:Example: + .. code-block:: none + + >> Issue: [B317:blacklist] Using xml.sax.parse to parse untrusted XML data + is known to be vulnerable to XML attacks. Replace xml.sax.parse with its + defusedxml equivalent function. + Severity: Medium Confidence: High + Location: ./examples/xml_sax.py:24 + 23 sax.parseString(xmlString, ExampleContentHandler()) + 24 sax.parse('notaxmlfilethatexists.xml', ExampleContentHandler) + 25 + +Complete Plugin Listing +----------------------- + +.. toctree:: + :maxdepth: 1 + :glob: + + * + +.. versionadded:: 0.17.0 diff --git a/doc/source/index.rst b/doc/source/index.rst index b74c5b93..8b71f88a 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -16,6 +16,7 @@ Getting Started config plugins/index + blacklists/index formatters/index Indices and tables diff --git a/doc/source/plugins/blacklist_import_func.rst b/doc/source/plugins/blacklist_import_func.rst deleted file mode 100644 index 6efe10c0..00000000 --- a/doc/source/plugins/blacklist_import_func.rst +++ /dev/null @@ -1,8 +0,0 @@ ---------------------- -blacklist_import_func ---------------------- - -.. currentmodule:: bandit.plugins.blacklist_imports - -.. autofunction:: blacklist_import_func - :noindex: diff --git a/doc/source/plugins/blacklist_imports.rst b/doc/source/plugins/blacklist_imports.rst deleted file mode 100644 index ea821201..00000000 --- a/doc/source/plugins/blacklist_imports.rst +++ /dev/null @@ -1,8 +0,0 @@ ------------------ -blacklist_imports ------------------ - -.. currentmodule:: bandit.plugins.blacklist_imports - -.. autofunction:: blacklist_imports - :noindex: