~ubuntu-branches/ubuntu/wily/bandit/wily-proposed

« back to all changes in this revision

Viewing changes to tests/test_functional.py

  • Committer: Package Import Robot
  • Author(s): Dave Walker (Daviey)
  • Date: 2015-07-22 09:01:39 UTC
  • Revision ID: package-import@ubuntu.com-20150722090139-fl0nluy0x8m9ctx4
Tags: upstream-0.12.0
ImportĀ upstreamĀ versionĀ 0.12.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding:utf-8 -*-
 
2
#
 
3
# Copyright 2014 Hewlett-Packard Development Company, L.P.
 
4
#
 
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
 
6
# not use this file except in compliance with the License. You may obtain
 
7
# a copy of the License at
 
8
#
 
9
#      http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
# Unless required by applicable law or agreed to in writing, software
 
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
14
# License for the specific language governing permissions and limitations
 
15
# under the License.
 
16
 
 
17
import os
 
18
 
 
19
import unittest
 
20
import inspect
 
21
 
 
22
import six
 
23
 
 
24
from bandit.core import constants as C
 
25
from bandit.core import manager as b_manager
 
26
from bandit.core import test_set as b_test_set
 
27
 
 
28
 
 
29
cfg_file = os.path.join(os.getcwd(), 'bandit/config/bandit.yaml')
 
30
 
 
31
 
 
32
class FunctionalTests(unittest.TestCase):
 
33
 
 
34
    '''This set of tests runs bandit against each example file in turn
 
35
    and records the score returned. This is compared to a known good value.
 
36
    When new tests are added to an example the expected result should be
 
37
    adjusted to match.
 
38
    '''
 
39
 
 
40
    def setUp(self):
 
41
        super(FunctionalTests, self).setUp()
 
42
        # NOTE(tkelsey): bandit is very sensitive to paths, so stitch
 
43
        # them up here for the testing environment.
 
44
        #
 
45
        path = os.path.join(os.getcwd(), 'bandit', 'plugins')
 
46
        self.b_mgr = b_manager.BanditManager(cfg_file, 'file')
 
47
        self.b_mgr.b_conf._settings['plugins_dir'] = path
 
48
        self.b_mgr.b_ts = b_test_set.BanditTestSet(self.b_mgr.logger,
 
49
                                                   config=self.b_mgr.b_conf,
 
50
                                                   profile=None)
 
51
 
 
52
    def tearDown(self):
 
53
        pass
 
54
 
 
55
    def run_example(self, example_script):
 
56
        '''A helper method to run the specified test
 
57
 
 
58
        This method runs the test, which populates the self.b_mgr.scores
 
59
        value. Call this directly if you need to run a test, but do not
 
60
        need to test the resulting scores against specified values.
 
61
        :param example_script: Filename of an example script to test
 
62
        '''
 
63
        path = os.path.join(os.getcwd(), 'examples', example_script)
 
64
        self.b_mgr.discover_files([path], True)
 
65
        self.b_mgr.run_tests()
 
66
 
 
67
    def check_example(self, example_script, expect):
 
68
        '''A helper method to test the scores for example scripts.
 
69
 
 
70
        :param example_script: Filename of an example script to test
 
71
        :param expect: dict with expected counts of issue types
 
72
        '''
 
73
        # reset scores for subsequent calls to check_example
 
74
        self.b_mgr.scores = []
 
75
        self.run_example(example_script)
 
76
        expected = 0
 
77
        result = 0
 
78
        for test_scores in self.b_mgr.scores:
 
79
            for score_type in test_scores:
 
80
                self.assertIn(score_type, expect)
 
81
                for rating in expect[score_type]:
 
82
                    expected += (
 
83
                        expect[score_type][rating] * C.RANKING_VALUES[rating]
 
84
                    )
 
85
                result += sum(test_scores[score_type])
 
86
        self.assertEqual(expected, result)
 
87
 
 
88
    def test_binding(self):
 
89
        '''Test the bind-to-0.0.0.0 example.'''
 
90
        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'MEDIUM': 1}}
 
91
        self.check_example('binding.py', expect)
 
92
 
 
93
    def test_crypto_md5(self):
 
94
        '''Test the `hashlib.md5` example.'''
 
95
        expect = {'SEVERITY': {'MEDIUM': 4}, 'CONFIDENCE': {'HIGH': 4}}
 
96
        self.check_example('crypto-md5.py', expect)
 
97
 
 
98
    def test_eval(self):
 
99
        '''Test the `eval` example.'''
 
100
        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'HIGH': 3}}
 
101
        self.check_example('eval.py', expect)
 
102
 
 
103
    def test_exec(self):
 
104
        '''Test the `exec` example.'''
 
105
        filename = 'exec-{}.py'
 
106
        if six.PY2:
 
107
            filename = filename.format('py2')
 
108
            expect = {'SEVERITY': {'MEDIUM': 2}, 'CONFIDENCE': {'HIGH': 2}}
 
109
        else:
 
110
            filename = filename.format('py3')
 
111
            expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}
 
112
        self.check_example(filename, expect)
 
113
 
 
114
    def test_exec_as_root(self):
 
115
        '''Test for the `run_as_root=True` keyword argument.'''
 
116
        expect = {'SEVERITY': {'LOW': 5}, 'CONFIDENCE': {'MEDIUM': 5}}
 
117
        self.check_example('exec-as-root.py', expect)
 
118
 
 
119
    def test_hardcoded_passwords(self):
 
120
        '''Test for hard-coded passwords.'''
 
121
        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'LOW': 2}}
 
122
        self.check_example('hardcoded-passwords.py', expect)
 
123
 
 
124
    def test_hardcoded_tmp(self):
 
125
        '''Test for hard-coded /tmp.'''
 
126
        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'MEDIUM': 1}}
 
127
        self.check_example('hardcoded-tmp.py', expect)
 
128
 
 
129
    def test_httplib_https(self):
 
130
        '''Test for `httplib.HTTPSConnection`.'''
 
131
        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}
 
132
        self.check_example('httplib_https.py', expect)
 
133
 
 
134
    def test_imports_aliases(self):
 
135
        '''Test the `import X as Y` syntax.'''
 
136
        expect = {
 
137
            'SEVERITY': {'LOW': 3, 'MEDIUM': 5, 'HIGH': 1},
 
138
            'CONFIDENCE': {'HIGH': 9}
 
139
        }
 
140
        self.check_example('imports-aliases.py', expect)
 
141
 
 
142
    def test_imports_from(self):
 
143
        '''Test the `from X import Y` syntax.'''
 
144
        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'HIGH': 3}}
 
145
        self.check_example('imports-from.py', expect)
 
146
 
 
147
    def test_imports_function(self):
 
148
        '''Test the `__import__` function.'''
 
149
        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}
 
150
        self.check_example('imports-function.py', expect)
 
151
 
 
152
    def test_imports_telnetlib(self):
 
153
        '''Test for `import telnetlib`.'''
 
154
        expect = {'SEVERITY': {'HIGH': 1}, 'CONFIDENCE': {'HIGH': 1}}
 
155
        self.check_example('imports-telnetlib.py', expect)
 
156
 
 
157
    def test_imports(self):
 
158
        '''Test for dangerous imports.'''
 
159
        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}
 
160
        self.check_example('imports.py', expect)
 
161
 
 
162
    def test_multiline_str(self):
 
163
        '''Test docstrings and multi-line strings are handled properly.'''
 
164
        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'MEDIUM': 3}}
 
165
        self.check_example('multiline-str.py', expect)
 
166
 
 
167
    def test_mktemp(self):
 
168
        '''Test for `tempfile.mktemp`.'''
 
169
        expect = {'SEVERITY': {'MEDIUM': 4}, 'CONFIDENCE': {'HIGH': 4}}
 
170
        self.check_example('mktemp.py', expect)
 
171
 
 
172
    def test_nonsense(self):
 
173
        '''Test that a syntactically invalid module is skipped.'''
 
174
        self.run_example('nonsense.py')
 
175
        self.assertEqual(1, len(self.b_mgr.b_rs.skipped))
 
176
 
 
177
    def test_okay(self):
 
178
        '''Test a vulnerability-free file.'''
 
179
        expect = {'SEVERITY': {}, 'CONFIDENCE': {}}
 
180
        self.check_example('okay.py', expect)
 
181
 
 
182
    def test_os_chmod(self):
 
183
        '''Test setting file permissions.'''
 
184
        filename = 'os-chmod-{}.py'
 
185
        if six.PY2:
 
186
            filename = filename.format('py2')
 
187
            expect = {
 
188
                'SEVERITY': {'MEDIUM': 2, 'HIGH': 9},
 
189
                'CONFIDENCE': {'HIGH': 10, 'MEDIUM': 1}
 
190
            }
 
191
        else:
 
192
            filename = filename.format('py3')
 
193
            expect = {
 
194
                'SEVERITY': {'MEDIUM': 2, 'HIGH': 9},
 
195
                'CONFIDENCE': {'HIGH': 10, 'MEDIUM': 1}
 
196
            }
 
197
        self.check_example('os-chmod.py', expect)
 
198
 
 
199
    def test_os_exec(self):
 
200
        '''Test for `os.exec*`.'''
 
201
        expect = {'SEVERITY': {'LOW': 8}, 'CONFIDENCE': {'MEDIUM': 8}}
 
202
        self.check_example('os-exec.py', expect)
 
203
 
 
204
    def test_os_popen(self):
 
205
        '''Test for `os.popen`.'''
 
206
        expect = {'SEVERITY': {'MEDIUM': 7}, 'CONFIDENCE': {'MEDIUM': 7}}
 
207
        self.check_example('os-popen.py', expect)
 
208
 
 
209
    def test_os_spawn(self):
 
210
        '''Test for `os.spawn*`.'''
 
211
        expect = {'SEVERITY': {'LOW': 8}, 'CONFIDENCE': {'MEDIUM': 8}}
 
212
        self.check_example('os-spawn.py', expect)
 
213
 
 
214
    def test_os_startfile(self):
 
215
        '''Test for `os.startfile`.'''
 
216
        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'MEDIUM': 3}}
 
217
        self.check_example('os-startfile.py', expect)
 
218
 
 
219
    def test_os_system(self):
 
220
        '''Test for `os.system`.'''
 
221
        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'MEDIUM': 1}}
 
222
        self.check_example('os_system.py', expect)
 
223
 
 
224
    def test_pickle(self):
 
225
        '''Test for the `pickle` module.'''
 
226
        expect = {
 
227
            'SEVERITY': {'LOW': 2, 'MEDIUM': 6},
 
228
            'CONFIDENCE': {'HIGH': 8 }
 
229
        }
 
230
        self.check_example('pickle_deserialize.py', expect)
 
231
 
 
232
    def test_popen_wrappers(self):
 
233
        '''Test the `popen2` and `commands` modules.'''
 
234
        expect = {'SEVERITY': {'MEDIUM': 7}, 'CONFIDENCE': {'MEDIUM': 7}}
 
235
        self.check_example('popen_wrappers.py', expect)
 
236
 
 
237
    def test_random_module(self):
 
238
        '''Test for the `random` module.'''
 
239
        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'HIGH': 3}}
 
240
        self.check_example('random_module.py', expect)
 
241
 
 
242
    def test_requests_ssl_verify_disabled(self):
 
243
        '''Test for the `requests` library skipping verification.'''
 
244
        expect = {'SEVERITY': {'HIGH': 2}, 'CONFIDENCE': {'HIGH': 2}}
 
245
        self.check_example('requests-ssl-verify-disabled.py', expect)
 
246
 
 
247
    def test_skip(self):
 
248
        '''Test `#nosec` and `#noqa` comments.'''
 
249
        expect = {'SEVERITY': {'LOW': 5}, 'CONFIDENCE': {'HIGH': 5}}
 
250
        self.check_example('skip.py', expect)
 
251
 
 
252
    def test_sql_statements_with_sqlalchemy(self):
 
253
        '''Test for SQL injection through string building.'''
 
254
        expect = {'SEVERITY': {'LOW': 4}, 'CONFIDENCE': {'LOW': 4}}
 
255
        self.check_example('sql_statements_with_sqlalchemy.py', expect)
 
256
 
 
257
    def test_sql_statements_without_sql_alchemy(self):
 
258
        '''Test for SQL injection without SQLAlchemy.'''
 
259
        expect = {'SEVERITY': {'MEDIUM': 4}, 'CONFIDENCE': {'LOW': 4}}
 
260
        self.check_example('sql_statements_without_sql_alchemy.py', expect)
 
261
 
 
262
    def test_ssl_insecure_version(self):
 
263
        '''Test for insecure SSL protocol versions.'''
 
264
        expect = {
 
265
            'SEVERITY': {'LOW': 1, 'MEDIUM': 10, 'HIGH': 7},
 
266
            'CONFIDENCE': {'LOW': 0, 'MEDIUM': 11, 'HIGH': 7}
 
267
        }
 
268
        self.check_example('ssl-insecure-version.py', expect)
 
269
 
 
270
    def test_subprocess_shell(self):
 
271
        '''Test for `subprocess.Popen` with `shell=True`.'''
 
272
        expect = {
 
273
            'SEVERITY': {'HIGH': 5, 'MEDIUM': 1, 'LOW': 7},
 
274
            'CONFIDENCE': {'HIGH': 13}
 
275
        }
 
276
        self.check_example('subprocess_shell.py', expect)
 
277
 
 
278
    def test_urlopen(self):
 
279
        '''Test for dangerous URL opening.'''
 
280
        expect = {'SEVERITY': {'MEDIUM': 6}, 'CONFIDENCE': {'HIGH': 6}}
 
281
        self.check_example('urlopen.py', expect)
 
282
 
 
283
    def test_utils_shell(self):
 
284
        '''Test for `utils.execute*` with `shell=True`.'''
 
285
        expect = {
 
286
            'SEVERITY': {'HIGH': 4, 'LOW': 1},
 
287
            'CONFIDENCE': {'HIGH': 5}
 
288
        }
 
289
        self.check_example('utils-shell.py', expect)
 
290
 
 
291
    def test_wildcard_injection(self):
 
292
        '''Test for wildcard injection in shell commands.'''
 
293
        expect = {
 
294
            'SEVERITY': {'HIGH': 5, 'MEDIUM':3, 'LOW': 6},
 
295
            'CONFIDENCE': {'MEDIUM': 8, 'HIGH': 6}
 
296
        }
 
297
        self.check_example('wildcard-injection.py', expect)
 
298
 
 
299
    def test_yaml(self):
 
300
        '''Test for `yaml.load`.'''
 
301
        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}
 
302
        self.check_example('yaml_load.py', expect)
 
303
 
 
304
    def test_jinja2_templating(self):
 
305
        '''Test jinja templating for potential XSS bugs.'''
 
306
        expect = {
 
307
            'SEVERITY': {'HIGH': 4},
 
308
            'CONFIDENCE': {'HIGH': 3, 'MEDIUM':1}
 
309
        }
 
310
        self.check_example('jinja2_templating.py', expect)
 
311
 
 
312
    def test_secret_config_option(self):
 
313
        '''Test for `secret=True` in Oslo's config.'''
 
314
        expect = {
 
315
            'SEVERITY': {'LOW': 1, 'MEDIUM': 2},
 
316
            'CONFIDENCE': {'MEDIUM': 3}
 
317
        }
 
318
        self.check_example('secret-config-option.py', expect)
 
319
 
 
320
    def test_mako_templating(self):
 
321
        '''Test Mako templates for XSS.'''
 
322
        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'HIGH': 3}}
 
323
        self.check_example('mako_templating.py', expect)
 
324
 
 
325
    def test_xml(self):
 
326
        '''Test xml vulnerabilities.'''
 
327
        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 4},
 
328
                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 4}}
 
329
        self.check_example('xml_etree_celementtree.py', expect)
 
330
 
 
331
        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 2},
 
332
                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 2}}
 
333
        self.check_example('xml_expatbuilder.py', expect)
 
334
 
 
335
        expect = {'SEVERITY': {'LOW': 3, 'HIGH': 1},
 
336
                  'CONFIDENCE': {'HIGH': 3, 'MEDIUM': 1}}
 
337
        self.check_example('xml_lxml.py', expect)
 
338
 
 
339
        expect = {'SEVERITY': {'LOW': 2, 'HIGH': 2},
 
340
                  'CONFIDENCE': {'HIGH': 2, 'MEDIUM': 2}}
 
341
        self.check_example('xml_pulldom.py', expect)
 
342
 
 
343
        expect = {'SEVERITY': {'HIGH': 1},
 
344
                  'CONFIDENCE': {'HIGH': 1}}
 
345
        self.check_example('xml_xmlrpc.py', expect)
 
346
 
 
347
        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 4},
 
348
                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 4}}
 
349
        self.check_example('xml_etree_elementtree.py', expect)
 
350
 
 
351
        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 1},
 
352
                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 1}}
 
353
        self.check_example('xml_expatreader.py', expect)
 
354
 
 
355
        expect = {'SEVERITY': {'LOW': 2, 'HIGH': 2},
 
356
                  'CONFIDENCE': {'HIGH': 2, 'MEDIUM': 2}}
 
357
        self.check_example('xml_minidom.py', expect)
 
358
 
 
359
        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 6},
 
360
                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 6}}
 
361
        self.check_example('xml_sax.py', expect)
 
362
 
 
363
    def test_asserts(self):
 
364
        '''Test catching the use of assert.'''
 
365
        expect = {'SEVERITY': {'LOW': 1},
 
366
                  'CONFIDENCE': {'HIGH': 1}}
 
367
        self.check_example('assert.py', expect)
 
368
 
 
369
    def test_paramiko_injection(self):
 
370
        '''Test paramiko command execution.'''
 
371
        expect = {'SEVERITY': {'MEDIUM': 2},
 
372
                  'CONFIDENCE': {'HIGH': 2}}
 
373
        self.check_example('paramiko_injection.py', expect)
 
374
 
 
375
    def test_multiline_code(self):
 
376
        '''Test issues in multiline statements return code as expected.'''
 
377
        self.run_example('multiline-str.py')
 
378
        self.assertEqual(0, len(self.b_mgr.b_rs.skipped))
 
379
        self.assertEqual(1, len(self.b_mgr.files_list))
 
380
        self.assertTrue(self.b_mgr.files_list[0].endswith('multiline-str.py'))
 
381
        issues = self.b_mgr.b_rs._get_issue_list()
 
382
        self.assertEqual(3, len(issues))
 
383
        self.assertTrue(
 
384
            issues[0]['filename'].endswith('examples/multiline-str.py')
 
385
        )
 
386
        self.assertEqual(4, issues[0]['line_number'])
 
387
        self.assertEqual(range(2, 7), issues[0]['line_range'])
 
388
        self.assertIn('/tmp', issues[0]['code'])
 
389
        self.assertEqual(18, issues[1]['line_number'])
 
390
        self.assertEqual(range(16, 21), issues[1]['line_range'])
 
391
        self.assertIn('/tmp', issues[1]['code'])
 
392
        self.assertEqual(23, issues[2]['line_number'])
 
393
        self.assertEqual(range(22, 31), issues[2]['line_range'])
 
394
        self.assertIn('/tmp', issues[2]['code'])