Modifying Paramiko Injection plugin

The way the paramiko check was previously working didn't catch
many uses because the qualified name is difficult to predict for
Paramiko calls.  This commit changes it so that paramiko detection
is accomplished by the combination of importing paramiko and using
one of the paramiko functions that executes with a shell.

Change-Id: Ib6e8f596a8f05475213be0ac8cf27e4e308b9617
This commit is contained in:
Travis McPeak 2015-07-14 08:34:41 -06:00
parent c7f582271c
commit d82506ea43
4 changed files with 31 additions and 11 deletions

View File

@ -77,9 +77,6 @@ blacklist_calls:
- urllib_urlopen:
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."
- paramiko_injection:
qualnames: [paramiko.exec_command, paramiko.invoke_shell]
message: "Paramiko exec_command() and invoke_shell() usage may expose command injection vulnerabilities and should be reviewed."
shell_injection:
# Start a process using the subprocess module, or one of its wrappers.

View File

@ -0,0 +1,29 @@
# -*- coding:utf-8 -*-
#
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import bandit
from bandit.core.test_properties import *
@checks('Call')
def paramiko_calls(context):
issue_text = 'Probable Paramiko shell execution, check inputs'
for module in ['paramiko']:
if context.is_module_imported_like(module):
if context.call_function_name in ['exec_command', 'invoke_shell']:
return bandit.Issue(severity=bandit.MEDIUM,
confidence=bandit.MEDIUM,
text=issue_text)

View File

@ -6,12 +6,6 @@ paramiko.exec_command('something; reallly; unsafe')
# this is safe
paramiko.connect('somehost')
# this should not be detected
somelib.exec_command('this; is; indeterminately; unsafe')
# this is not safe
paramiko.invoke_shell('something; bad; here\n')
# should not be detected
somelib.invoke_shell('this; is; indeterminately; unsafe')
SSHClient.invoke_shell('something; bad; here\n')

View File

@ -369,7 +369,7 @@ class FunctionalTests(unittest.TestCase):
def test_paramiko_injection(self):
'''Test paramiko command execution.'''
expect = {'SEVERITY': {'MEDIUM': 2},
'CONFIDENCE': {'HIGH': 2}}
'CONFIDENCE': {'MEDIUM': 2}}
self.check_example('paramiko_injection.py', expect)
def test_partial_path(self):