src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/blackListCalls.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2020 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing checks for blacklisted methods and functions.
8 """
9
10 #
11 # This is a modified version of the one found in the bandit package.
12 #
13 # Original Copyright 2016 Hewlett-Packard Development Company, L.P.
14 #
15 # SPDX-License-Identifier: Apache-2.0
16 #
17
18 import ast
19 import fnmatch
20
21 import AstUtilities
22
23 _blacklists = {
24 'S301': ([
25 'pickle.loads',
26 'pickle.load',
27 'pickle.Unpickler',
28 'cPickle.loads',
29 'cPickle.load',
30 'cPickle.Unpickler',
31 'dill.loads',
32 'dill.load',
33 'dill.Unpickler',
34 'shelve.open',
35 'shelve.DbfilenameShelf'],
36 "M"),
37 'S302': ([
38 'marshal.load',
39 'marshal.loads'],
40 "M"),
41 'S303': ([
42 'hashlib.md5',
43 'hashlib.sha1',
44 'Crypto.Hash.MD2.new',
45 'Crypto.Hash.MD4.new',
46 'Crypto.Hash.MD5.new',
47 'Crypto.Hash.SHA.new',
48 'Cryptodome.Hash.MD2.new',
49 'Cryptodome.Hash.MD4.new',
50 'Cryptodome.Hash.MD5.new',
51 'Cryptodome.Hash.SHA.new',
52 'cryptography.hazmat.primitives.hashes.MD5',
53 'cryptography.hazmat.primitives.hashes.SHA1'],
54 "M"),
55 'S304': ([
56 'Crypto.Cipher.ARC2.new',
57 'Crypto.Cipher.ARC4.new',
58 'Crypto.Cipher.Blowfish.new',
59 'Crypto.Cipher.DES.new',
60 'Crypto.Cipher.XOR.new',
61 'Cryptodome.Cipher.ARC2.new',
62 'Cryptodome.Cipher.ARC4.new',
63 'Cryptodome.Cipher.Blowfish.new',
64 'Cryptodome.Cipher.DES.new',
65 'Cryptodome.Cipher.XOR.new',
66 'cryptography.hazmat.primitives.ciphers.algorithms.ARC4',
67 'cryptography.hazmat.primitives.ciphers.algorithms.Blowfish',
68 'cryptography.hazmat.primitives.ciphers.algorithms.IDEA'],
69 "H"),
70 'S305': ([
71 'cryptography.hazmat.primitives.ciphers.modes.ECB'],
72 "M"),
73 'S306': ([
74 'tempfile.mktemp'],
75 "M"),
76 'S307': ([
77 'eval'],
78 "M"),
79 'S308': ([
80 'django.utils.safestring.mark_safe'],
81 "M"),
82 'S309': ([
83 'httplib.HTTPSConnection',
84 'http.client.HTTPSConnection',
85 'six.moves.http_client.HTTPSConnection'],
86 "M"),
87 'S310': ([
88 'urllib.urlopen',
89 'urllib.request.urlopen',
90 'urllib.urlretrieve',
91 'urllib.request.urlretrieve',
92 'urllib.URLopener',
93 'urllib.request.URLopener',
94 'urllib.FancyURLopener',
95 'urllib.request.FancyURLopener',
96 'urllib2.urlopen',
97 'urllib2.Request',
98 'six.moves.urllib.request.urlopen',
99 'six.moves.urllib.request.urlretrieve',
100 'six.moves.urllib.request.URLopener',
101 'six.moves.urllib.request.FancyURLopener'],
102 ""),
103 'S311': ([
104 'random.random',
105 'random.randrange',
106 'random.randint',
107 'random.choice',
108 'random.uniform',
109 'random.triangular'],
110 "L"),
111 'S312': ([
112 'telnetlib.*'],
113 "H"),
114 'S313': ([
115 'xml.etree.cElementTree.parse',
116 'xml.etree.cElementTree.iterparse',
117 'xml.etree.cElementTree.fromstring',
118 'xml.etree.cElementTree.XMLParser'],
119 "M"),
120 'S314': ([
121 'xml.etree.ElementTree.parse',
122 'xml.etree.ElementTree.iterparse',
123 'xml.etree.ElementTree.fromstring',
124 'xml.etree.ElementTree.XMLParser'],
125 "M"),
126 'S315': ([
127 'xml.sax.expatreader.create_parser'],
128 "M"),
129 'S316': ([
130 'xml.dom.expatbuilder.parse',
131 'xml.dom.expatbuilder.parseString'],
132 "M"),
133 'S317': ([
134 'xml.sax.parse',
135 'xml.sax.parseString',
136 'xml.sax.make_parser'],
137 "M"),
138 'S318': ([
139 'xml.dom.minidom.parse',
140 'xml.dom.minidom.parseString'],
141 "M"),
142 'S319': ([
143 'xml.dom.pulldom.parse',
144 'xml.dom.pulldom.parseString'],
145 "M"),
146 'S320': ([
147 'lxml.etree.parse',
148 'lxml.etree.fromstring',
149 'lxml.etree.RestrictedElement',
150 'lxml.etree.GlobalParserTLS',
151 'lxml.etree.getDefaultParser',
152 'lxml.etree.check_docinfo'],
153 "M"),
154 'S321': ([
155 'ftplib.*'],
156 "H"),
157 'S322': ([
158 'input'],
159 "H"),
160 'S323': ([
161 'ssl._create_unverified_context'],
162 "M"),
163 'S324': ([
164 'os.tempnam',
165 'os.tmpnam'],
166 "M"),
167 }
168
169
170 def getChecks():
171 """
172 Public method to get a dictionary with checks handled by this module.
173
174 @return dictionary containing checker lists containing checker function and
175 list of codes
176 @rtype dict
177 """
178 return {
179 "Call": [
180 (checkBlacklist, tuple(_blacklists.keys())),
181 ],
182 }
183
184
185 def checkBlacklist(reportError, context, config):
186 """
187 Function to check for blacklisted method calls.
188
189 @param reportError function to be used to report errors
190 @type func
191 @param context security context object
192 @type SecurityContext
193 @param config dictionary with configuration data
194 @type dict
195 """
196 nodeType = context.node.__class__.__name__
197
198 if nodeType == 'Call':
199 func = context.node.func
200 if isinstance(func, ast.Name) and func.id == '__import__':
201 if len(context.node.args):
202 if AstUtilities.isString(context.node.args[0]):
203 name = context.node.args[0].s
204 else:
205 name = "UNKNOWN"
206 else:
207 name = "" # handle '__import__()'
208 else:
209 name = context.callFunctionNameQual
210 # In the case the Call is an importlib.import, treat the first
211 # argument name as an actual import module name.
212 # Will produce None if argument is not a literal or identifier.
213 if name in ["importlib.import_module", "importlib.__import__"]:
214 name = context.callArgs[0]
215
216 for code in _blacklists:
217 qualnames, severity = _blacklists[code]
218 for qualname in qualnames:
219 if name and fnmatch.fnmatch(name, qualname):
220 reportError(
221 context.node.lineno - 1,
222 context.node.col_offset,
223 code,
224 severity,
225 "H",
226 name
227 )

eric ide

mercurial