Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 36bd520

Browse filesBrowse files
committed
Use import_alias_mapping for blackbox and built-in aliases, as well
* This will give fully qualified names for blackboxes like flask * Improve readability by using keyword arguments
1 parent 40c1f24 commit 36bd520
Copy full SHA for 36bd520

File tree

Expand file treeCollapse file tree

5 files changed

+132
-112
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+132
-112
lines changed

‎examples/vulnerable_code/command_injection_with_aliases.py

Copy file name to clipboardExpand all lines: examples/vulnerable_code/command_injection_with_aliases.py
+25-6Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,28 @@
44
from os import system as mysystem
55
from subprocess import call as mycall, Popen as mypopen
66

7-
os.system("ls")
8-
myos.system("ls")
9-
system("ls")
10-
mysystem("ls")
11-
mycall("ls")
12-
mypopen("ls")
7+
from flask import Flask, render_template, request
8+
9+
app = Flask(__name__)
10+
11+
12+
@app.route('/menu', methods=['POST'])
13+
def menu():
14+
param = request.form['suggestion']
15+
command = 'echo ' + param + ' >> ' + 'menu.txt'
16+
17+
os.system(command)
18+
myos.system(command)
19+
system(command)
20+
mysystem(command)
21+
mycall(command)
22+
mypopen(command)
23+
24+
with open('menu.txt', 'r') as f:
25+
menu_ctx = f.read()
26+
27+
return render_template('command_injection.html', menu=menu_ctx)
28+
29+
30+
if __name__ == '__main__':
31+
app.run(debug=True)

‎pyt/cfg/stmt_visitor.py

Copy file name to clipboardExpand all lines: pyt/cfg/stmt_visitor.py
+75-74Lines changed: 75 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
class StmtVisitor(ast.NodeVisitor):
6363
def __init__(self, allow_local_directory_imports=True):
6464
self._allow_local_modules = allow_local_directory_imports
65-
self.bb_or_bi_aliases = {}
6665
super().__init__()
6766

6867
def visit_Module(self, node):
@@ -628,7 +627,8 @@ def add_blackbox_or_builtin_call(self, node, blackbox): # noqa: C901
628627

629628
# Check if function call matches a blackbox/built-in alias and if so, resolve it
630629
# This resolves aliases like "from os import system as mysys" as: mysys -> os.system
631-
call_function_label = fully_qualify_alias_labels(call_function_label, self.bb_or_bi_aliases)
630+
local_definitions = self.module_definitions_stack[-1]
631+
call_function_label = fully_qualify_alias_labels(call_function_label, local_definitions.import_alias_mapping)
632632

633633
# Create e.g. ~call_1 = ret_func_foo
634634
LHS = CALL_IDENTIFIER + 'call_' + str(saved_function_call_index)
@@ -924,10 +924,10 @@ def from_directory_import(
924924
if init_exists and not skip_init:
925925
package_name = os.path.split(module_path)[1]
926926
return self.add_module(
927-
(module[0], init_file_location),
928-
package_name,
929-
local_names,
930-
import_alias_mapping,
927+
module=(module[0], init_file_location),
928+
module_or_package_name=package_name,
929+
local_names=local_names,
930+
import_alias_mapping=import_alias_mapping,
931931
is_init=True,
932932
from_from=True
933933
)
@@ -937,10 +937,10 @@ def from_directory_import(
937937
new_init_file_location = os.path.join(full_name, '__init__.py')
938938
if os.path.isfile(new_init_file_location):
939939
self.add_module(
940-
(real_name, new_init_file_location),
941-
real_name,
942-
local_names,
943-
import_alias_mapping,
940+
module=(real_name, new_init_file_location),
941+
module_or_package_name=real_name,
942+
local_names=local_names,
943+
import_alias_mapping=import_alias_mapping,
944944
is_init=True,
945945
from_from=True,
946946
from_fdid=True
@@ -950,10 +950,10 @@ def from_directory_import(
950950
else:
951951
file_module = (real_name, full_name + '.py')
952952
self.add_module(
953-
file_module,
954-
real_name,
955-
local_names,
956-
import_alias_mapping,
953+
module=file_module,
954+
module_or_package_name=real_name,
955+
local_names=local_names,
956+
import_alias_mapping=import_alias_mapping,
957957
from_from=True
958958
)
959959
return IgnoredNode()
@@ -964,10 +964,10 @@ def import_package(self, module, module_name, local_name, import_alias_mapping):
964964
init_exists = os.path.isfile(init_file_location)
965965
if init_exists:
966966
return self.add_module(
967-
(module[0], init_file_location),
968-
module_name,
969-
local_name,
970-
import_alias_mapping,
967+
module=(module[0], init_file_location),
968+
module_or_package_name=module_name,
969+
local_names=local_name,
970+
import_alias_mapping=import_alias_mapping,
971971
is_init=True
972972
)
973973
else:
@@ -1010,10 +1010,10 @@ def handle_relative_import(self, node):
10101010
# Is it a file?
10111011
if name_with_dir.endswith('.py'):
10121012
return self.add_module(
1013-
(node.module, name_with_dir),
1014-
None,
1015-
as_alias_handler(node.names),
1016-
retrieve_import_alias_mapping(node.names),
1013+
module=(node.module, name_with_dir),
1014+
module_or_package_name=None,
1015+
local_names=as_alias_handler(node.names),
1016+
import_alias_mapping=retrieve_import_alias_mapping(node.names),
10171017
from_from=True
10181018
)
10191019
return self.from_directory_import(
@@ -1036,10 +1036,10 @@ def visit_Import(self, node):
10361036
retrieve_import_alias_mapping(node.names)
10371037
)
10381038
return self.add_module(
1039-
module,
1040-
name.name,
1041-
name.asname,
1042-
retrieve_import_alias_mapping(node.names)
1039+
module=module,
1040+
module_or_package_name=name.name,
1041+
local_names=name.asname,
1042+
import_alias_mapping=retrieve_import_alias_mapping(node.names)
10431043
)
10441044
for module in self.project_modules:
10451045
if name.name == module[0]:
@@ -1051,68 +1051,69 @@ def visit_Import(self, node):
10511051
retrieve_import_alias_mapping(node.names)
10521052
)
10531053
return self.add_module(
1054-
module,
1055-
name.name,
1056-
name.asname,
1057-
retrieve_import_alias_mapping(node.names)
1054+
module=module,
1055+
module_or_package_name=name.name,
1056+
local_names=name.asname,
1057+
import_alias_mapping=retrieve_import_alias_mapping(node.names)
10581058
)
10591059
for alias in node.names:
1060-
if alias.name in uninspectable_modules:
1061-
# The module is uninspectable (so blackbox or built-in). If it has an alias, we remember
1062-
# the alias so we can do fully qualified name resolution for blackbox- and built-in trigger words
1063-
# e.g. we want a call to "os.system" be recognised, even if we do "import os as myos"
1064-
if alias.asname is not None and alias.asname != alias.name:
1065-
self.bb_or_bi_aliases[alias.asname] = alias.name
1066-
else:
1067-
log.warn("Cannot inspect module %s", alias.name)
1060+
# The module is uninspectable (so blackbox or built-in). If it has an alias, we remember
1061+
# the alias so we can do fully qualified name resolution for blackbox- and built-in trigger words
1062+
# e.g. we want a call to "os.system" be recognised, even if we do "import os as myos"
1063+
if alias.asname is not None and alias.asname != alias.name:
1064+
local_definitions = self.module_definitions_stack[-1]
1065+
local_definitions.import_alias_mapping[name.asname] = alias.name
1066+
if alias.name not in uninspectable_modules:
1067+
log.warning("Cannot inspect module %s", alias.name)
10681068
uninspectable_modules.add(alias.name) # Don't repeatedly warn about this
10691069
return IgnoredNode()
10701070

10711071
def visit_ImportFrom(self, node):
10721072
# Is it relative?
10731073
if node.level > 0:
10741074
return self.handle_relative_import(node)
1075-
else:
1076-
for module in self.local_modules:
1077-
if node.module == module[0]:
1078-
if os.path.isdir(module[1]):
1079-
return self.from_directory_import(
1080-
module,
1081-
not_as_alias_handler(node.names),
1082-
as_alias_handler(node.names)
1083-
)
1084-
return self.add_module(
1075+
# not relative
1076+
for module in self.local_modules:
1077+
if node.module == module[0]:
1078+
if os.path.isdir(module[1]):
1079+
return self.from_directory_import(
10851080
module,
1086-
None,
1087-
as_alias_handler(node.names),
1088-
retrieve_import_alias_mapping(node.names),
1089-
from_from=True
1081+
not_as_alias_handler(node.names),
1082+
as_alias_handler(node.names)
10901083
)
1091-
for module in self.project_modules:
1092-
name = module[0]
1093-
if node.module == name:
1094-
if os.path.isdir(module[1]):
1095-
return self.from_directory_import(
1096-
module,
1097-
not_as_alias_handler(node.names),
1098-
as_alias_handler(node.names),
1099-
retrieve_import_alias_mapping(node.names)
1100-
)
1101-
return self.add_module(
1084+
return self.add_module(
1085+
module=module,
1086+
module_or_package_name=None,
1087+
local_names=as_alias_handler(node.names),
1088+
import_alias_mapping=retrieve_import_alias_mapping(node.names),
1089+
from_from=True
1090+
)
1091+
for module in self.project_modules:
1092+
name = module[0]
1093+
if node.module == name:
1094+
if os.path.isdir(module[1]):
1095+
return self.from_directory_import(
11021096
module,
1103-
None,
1097+
not_as_alias_handler(node.names),
11041098
as_alias_handler(node.names),
1105-
retrieve_import_alias_mapping(node.names),
1106-
from_from=True
1099+
retrieve_import_alias_mapping(node.names)
11071100
)
1101+
return self.add_module(
1102+
module=module,
1103+
module_or_package_name=None,
1104+
local_names=as_alias_handler(node.names),
1105+
import_alias_mapping=retrieve_import_alias_mapping(node.names),
1106+
from_from=True
1107+
)
11081108

1109-
if node.module in uninspectable_modules:
1110-
# Remember aliases for blackboxed and built-in imports such that we can label them fully qualified
1111-
# e.g. we want a call to "os.system" be recognised, even if we do "from os import system"
1112-
# from os import system as mysystem -> module=os, name=system, asname=mysystem
1113-
for name in node.names:
1114-
self.bb_or_bi_aliases[name.asname or name.name] = "{}.{}".format(node.module, name.name)
1115-
else:
1116-
log.warn("Cannot inspect module %s", node.module)
1109+
# Remember aliases for uninspecatble modules such that we can label them fully qualified
1110+
# e.g. we want a call to "os.system" be recognised, even if we do "from os import system"
1111+
# from os import system as mysystem -> module=os, name=system, asname=mysystem
1112+
for name in node.names:
1113+
local_definitions = self.module_definitions_stack[-1]
1114+
local_definitions.import_alias_mapping[name.asname or name.name] = "{}.{}".format(node.module, name.name)
1115+
1116+
if node.module not in uninspectable_modules:
1117+
log.warning("Cannot inspect module %s", node.module)
11171118
uninspectable_modules.add(node.module)
11181119
return IgnoredNode()

‎tests/vulnerabilities/vulnerabilities_across_files_test.py

Copy file name to clipboardExpand all lines: tests/vulnerabilities/vulnerabilities_across_files_test.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_blackbox_library_call(self):
6262
EXPECTED_VULNERABILITY_DESCRIPTION = """
6363
File: examples/vulnerable_code_across_files/blackbox_library_call.py
6464
> User input at line 12, source "request.args.get(":
65-
~call_1 = ret_request.args.get('suggestion')
65+
~call_1 = ret_flask.request.args.get('suggestion')
6666
Reassigned in:
6767
File: examples/vulnerable_code_across_files/blackbox_library_call.py
6868
> Line 12: param = ~call_1

‎tests/vulnerabilities/vulnerabilities_base_test_case.py

Copy file name to clipboardExpand all lines: tests/vulnerabilities/vulnerabilities_base_test_case.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def string_compare_alpha(self, output, expected_string):
1111

1212
def assertAlphaEqual(self, output, expected_string):
1313
self.assertEqual(
14-
[char for char in output if char.isalpha()],
15-
[char for char in expected_string if char.isalpha()]
14+
''.join(char for char in output if char.isalpha()),
15+
''.join(char for char in expected_string if char.isalpha())
1616
)
1717
return True

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.