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

« back to all changes in this revision

Viewing changes to bandit/plugins/injection_sql.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 bandit
 
18
from bandit.core.test_properties import *
 
19
from bandit.core import utils
 
20
 
 
21
 
 
22
def _ast_build_string(data):
 
23
    # used to return a string representation of AST data
 
24
 
 
25
    if isinstance(data, ast.Str):
 
26
        # Already a string, just return the value
 
27
        return utils.safe_str(data.s)
 
28
 
 
29
    if isinstance(data, ast.BinOp):
 
30
        # need to build the string from a binary operation
 
31
        return _ast_binop_stringify(data)
 
32
 
 
33
    if isinstance(data, ast.Name):
 
34
        # a variable, stringify the variable name
 
35
        return "[[" + utils.safe_str(data.id) + "]]"
 
36
 
 
37
    return "XXX"  # placeholder for unaccounted for values
 
38
 
 
39
 
 
40
def _ast_binop_stringify(data):
 
41
    # used to recursively build a string from a binary operation
 
42
    left = data.left
 
43
    right = data.right
 
44
 
 
45
    return _ast_build_string(left) + _ast_build_string(right)
 
46
 
 
47
 
 
48
@checks('Str')
 
49
def hardcoded_sql_expressions(context):
 
50
    statement = context.statement['node']
 
51
    if isinstance(statement, ast.Assign):
 
52
        test_str = _ast_build_string(statement.value).lower()
 
53
 
 
54
    elif isinstance(statement, ast.Expr):
 
55
        test_str = ""
 
56
        if isinstance(statement.value, ast.Call):
 
57
            ctx_str = context.string_val.lower()
 
58
            for arg in statement.value.args:
 
59
                temp_str = _ast_build_string(arg).lower()
 
60
                if ctx_str in temp_str:
 
61
                    test_str = temp_str
 
62
    else:
 
63
        test_str = context.string_val.lower()
 
64
 
 
65
    if (
 
66
        (test_str.startswith('select ') and ' from ' in test_str) or
 
67
        test_str.startswith('insert into') or
 
68
        (test_str.startswith('update ') and ' set ' in test_str) or
 
69
        test_str.startswith('delete from ')
 
70
    ):
 
71
        # if sqlalchemy is not imported and it looks like they are using SQL
 
72
        # statements, mark it as a medium severity issue
 
73
        if not context.is_module_imported_like("sqlalchemy"):
 
74
            return bandit.Issue(
 
75
                severity=bandit.MEDIUM,
 
76
                confidence=bandit.LOW,
 
77
                text="Possible SQL injection vector through string-based "
 
78
                     "query construction, without SQLAlchemy use."
 
79
            )
 
80
 
 
81
        # otherwise, if sqlalchemy is being used, mark it as low severity
 
82
        else:
 
83
            return bandit.Issue(
 
84
                severity=bandit.LOW,
 
85
                confidence=bandit.LOW,
 
86
                text="Possible SQL injection vector through string-based "
 
87
                     "query construction."
 
88
            )