Update the config file, and use yaml.safe_load()

- Parse the config file with yaml.safe_load(), not yaml.load().
- Use YAML lists for the blacklist functions/imports plugins.
- Add plugins to the ShellInjection profile in the config.
- Don't blacklist user-defined methods named `eval`.

Change-Id: I437eedc4bfd56c96116cb92fe555968cf0f8dd63
This commit is contained in:
David Wyde 2015-03-12 15:43:40 -05:00
parent fc91927698
commit f0655ee323
5 changed files with 37 additions and 43 deletions

View File

@ -37,6 +37,8 @@ profiles:
include:
- subprocess_popen_with_shell_equals_true
- any_other_function_with_shell_equals_true
- start_process_with_a_shell
- start_process_with_no_shell
exclude:
SqlInjection:
@ -46,32 +48,32 @@ profiles:
blacklist_functions:
bad_name_sets:
- pickle:
qualname: pickle.loads, pickle.load, pickle.Unpickler,
cPickle.loads, cPickle.load, cPickle.Unpickler
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:
qualname: marshal.load, marshal.loads
qualnames: [marshal.load, marshal.loads]
message: "Deserialization with the marshal module is possibly dangerous."
- md5:
qualname: hashlib.md5
qualnames: [hashlib.md5]
message: "Use of insecure MD5 hash function."
- mktemp_q:
qualname: tempfile.mktemp
qualnames: [tempfile.mktemp]
message: "Use of insecure and deprecated function (mktemp)."
- eval:
name: eval
qualnames: [eval]
message: "Use of possibly insecure function - consider using safer ast.literal_eval."
- mark_safe:
name: mark_safe
names: [mark_safe]
message: "Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed."
- httpsconnection:
qualname: httplib.HTTPSConnection
qualnames: [httplib.HTTPSConnection]
message: "Use of HTTPSConnection does not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033"
- yaml_load:
qualname: yaml.load
qualnames: [yaml.load]
message: "Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load()."
- urllib_urlopen:
qualname: urllib.urlopen, urllib.urlretrieve, urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen, urllib2.Request
qualnames: [urllib.urlopen, urllib.urlretrieve, urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen, urllib2.Request]
message: "Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected."
shell_injection:
@ -91,11 +93,11 @@ shell_injection:
blacklist_imports:
bad_import_sets:
- telnet:
import: telnetlib
imports: [telnetlib]
level: ERROR
message: "Telnet is considered insecure. Use SSH or some other encrypted protocol."
- info_libs:
import: pickle, cPickle, subprocess, Crypto
imports: [pickle, cPickle, subprocess, Crypto]
level: INFO
message: "Consider possible security implications associated with {module} module."

View File

@ -44,7 +44,7 @@ class BanditConfig():
sys.exit(2)
else:
# yaml parser does its own exception handling
self._config = yaml.load(f)
self._config = yaml.safe_load(f)
self._init_settings()

View File

@ -91,20 +91,10 @@ def _get_tuple_for_item(blacklist_object):
if not isinstance(blacklist_object, dict):
return None
if 'qualname' in blacklist_object:
qualname_list = blacklist_object['qualname'].split(',')
for q in qualname_list:
if not qualnames:
qualnames = []
qualnames.append(q.replace(' ', '').strip())
if 'name' in blacklist_object:
name_list = blacklist_object['name'].split(',')
for n in name_list:
if not names:
names = []
names.append(n.replace(' ', '').strip())
if 'qualnames' in blacklist_object:
qualnames = blacklist_object['qualnames']
if 'names' in blacklist_object:
names = blacklist_object['names']
if 'message' in blacklist_object:
message = blacklist_object['message']
@ -116,12 +106,8 @@ def _get_tuple_for_item(blacklist_object):
elif blacklist_object['level'] == 'INFO':
level = 'INFO'
if 'param' in blacklist_object:
param_list = blacklist_object['param'].split(',')
for p in param_list:
if not params:
params = []
params.append(p.replace(' ', '').strip())
if 'params' in blacklist_object:
params = blacklist_object['params']
return_tuple = (qualnames, names, message, level, params)
return return_tuple

View File

@ -71,18 +71,13 @@ def _get_tuple_for_item(blacklist_object):
level = 'WARN'
# if the item we got passed isn't a dictionary, do nothing with the object;
# if the item we got passed doesn't have an import field, or the import
# isn't a string, we can't do anything with this. Return None
if(not isinstance(blacklist_object, dict)
or 'import' not in blacklist_object
or not type(blacklist_object['import']) == str):
# if the item we got passed doesn't have an imports field, we can't do
# anything with this. Return None
if (not isinstance(blacklist_object, dict)
or 'imports' not in blacklist_object):
return None
import_list = blacklist_object['import'].split(',')
for i in import_list:
if not imports:
imports = []
imports.append(i.replace(' ', '').strip())
imports = blacklist_object['imports']
if 'message' in blacklist_object:
message = blacklist_object['message']
@ -94,6 +89,7 @@ def _get_tuple_for_item(blacklist_object):
level = 'WARN'
elif blacklist_object['level'] == 'INFO':
level = 'INFO'
return_tuple = (imports, message, level)
return return_tuple

View File

@ -3,3 +3,13 @@ import os
print(eval("1+1"))
print(eval("os.getcwd()"))
print(eval("os.chmod('%s', 0777)" % 'test.txt'))
# A user-defined method named "eval" should not get flagged.
class Test(object):
def eval(self):
print("hi")
def foo(self):
self.eval()
Test().eval()