35 ], |
35 ], |
36 } |
36 } |
37 |
37 |
38 |
38 |
39 SIMPLE_SQL_RE = re.compile( |
39 SIMPLE_SQL_RE = re.compile( |
40 r'(select\s.*from\s|' |
40 r"(select\s.*from\s|" |
41 r'delete\s+from\s|' |
41 r"delete\s+from\s|" |
42 r'insert\s+into\s.*values\s|' |
42 r"insert\s+into\s.*values\s|" |
43 r'update\s.*set\s)', |
43 r"update\s.*set\s)", |
44 re.IGNORECASE | re.DOTALL, |
44 re.IGNORECASE | re.DOTALL, |
45 ) |
45 ) |
46 |
46 |
47 |
47 |
48 def _checkString(data): |
48 def _checkString(data): |
49 """ |
49 """ |
50 Function to check a given string against the list of search patterns. |
50 Function to check a given string against the list of search patterns. |
51 |
51 |
52 @param data string data to be checked |
52 @param data string data to be checked |
53 @type str |
53 @type str |
54 @return flag indicating a match |
54 @return flag indicating a match |
55 @rtype bool |
55 @rtype bool |
56 """ |
56 """ |
58 |
58 |
59 |
59 |
60 def _evaluateAst(node): |
60 def _evaluateAst(node): |
61 """ |
61 """ |
62 Function to analyze the given ast node. |
62 Function to analyze the given ast node. |
63 |
63 |
64 @param node ast node to be analyzed |
64 @param node ast node to be analyzed |
65 @type ast.Str |
65 @type ast.Str |
66 @return tuple containing a flag indicating an execute call and |
66 @return tuple containing a flag indicating an execute call and |
67 the resulting statement |
67 the resulting statement |
68 @rtype tuple of (bool, str) |
68 @rtype tuple of (bool, str) |
69 """ |
69 """ |
70 wrapper = None |
70 wrapper = None |
71 statement = '' |
71 statement = "" |
72 |
72 |
73 if isinstance(node._securityParent, ast.BinOp): |
73 if isinstance(node._securityParent, ast.BinOp): |
74 out = SecurityUtils.concatString(node, node._securityParent) |
74 out = SecurityUtils.concatString(node, node._securityParent) |
75 wrapper = out[0]._securityParent |
75 wrapper = out[0]._securityParent |
76 statement = out[1] |
76 statement = out[1] |
77 elif ( |
77 elif ( |
78 isinstance(node._securityParent, ast.Attribute) and |
78 isinstance(node._securityParent, ast.Attribute) |
79 node._securityParent.attr == 'format' |
79 and node._securityParent.attr == "format" |
80 ): |
80 ): |
81 statement = node.s |
81 statement = node.s |
82 # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str |
82 # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str |
83 wrapper = node._securityParent._securityParent._securityParent |
83 wrapper = node._securityParent._securityParent._securityParent |
84 elif ( |
84 elif hasattr(ast, "JoinedStr") and isinstance(node._securityParent, ast.JoinedStr): |
85 hasattr(ast, 'JoinedStr') and |
|
86 isinstance(node._securityParent, ast.JoinedStr) |
|
87 ): |
|
88 statement = node.s |
85 statement = node.s |
89 wrapper = node._securityParent._securityParent |
86 wrapper = node._securityParent._securityParent |
90 |
87 |
91 if isinstance(wrapper, ast.Call): # wrapped in "execute" call? |
88 if isinstance(wrapper, ast.Call): # wrapped in "execute" call? |
92 names = ['execute', 'executemany'] |
89 names = ["execute", "executemany"] |
93 name = SecurityUtils.getCalledName(wrapper) |
90 name = SecurityUtils.getCalledName(wrapper) |
94 return (name in names, statement) |
91 return (name in names, statement) |
95 else: |
92 else: |
96 return (False, statement) |
93 return (False, statement) |
97 |
94 |
98 |
95 |
99 def checkHardcodedSqlExpressions(reportError, context, config): |
96 def checkHardcodedSqlExpressions(reportError, context, config): |
100 """ |
97 """ |
101 Function to check for SQL injection. |
98 Function to check for SQL injection. |
102 |
99 |
103 @param reportError function to be used to report errors |
100 @param reportError function to be used to report errors |
104 @type func |
101 @type func |
105 @param context security context object |
102 @param context security context object |
106 @type SecurityContext |
103 @type SecurityContext |
107 @param config dictionary with configuration data |
104 @param config dictionary with configuration data |