Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = picklescan
version = 1.0.0
version = 1.0.1
author = Matthieu Maitre
author_email = mmaitre314@users.noreply.github.com
description = Security scanner detecting Python Pickle files performing suspicious actions
Expand Down
1 change: 1 addition & 0 deletions src/picklescan/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def __str__(self) -> str:
"ctypes": "*", # Foreign function interface, can load DLLs, call C functions, manipulate raw memory
"functools": "partial", # functools.partial(os.system, "echo pwned")
"httplib": "*", # Includes http.client.HTTPSConnection()
"logging": {"FileHandler"}, # logging.FileHandler can create arbitrary files on the filesystem
"_io": {"FileIO"}, # io.FileIO is stored as _io.FileIO, can read arbitrary files bypassing builtins.open blocklist
"numpy.f2py": "*", # Multiple unsafe functions (e.g., getlincoef, _eval_length) that call eval on arbitrary strings
"numpy.testing._private.utils": "*", # runstring() in this module is a synonym for exec()
Expand Down
Binary file added tests/data2/logging_FileHandler.pkl
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/init_data_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ def reduce_GHSA_49gj_c84q_6qm9():
return cProfile.run, (_payload,)


def reduce_logging_FileHandler():
from logging import FileHandler

return FileHandler, ("evil.log",)


def reduce_GHSA_q77w_mwjj_7mqx():
if sys.platform == "win32":
sys.platform = "mock"
Expand Down Expand Up @@ -842,6 +848,7 @@ def initialize_pickle_files():
initialize_pickle_file_from_reduce("GHSA-r8g5-cgf2-4m4m.pkl", reduce_GHSA_r8g5_cgf2_4m4m)
initialize_pickle_file_from_reduce("io_FileIO.pkl", reduce_io_FileIO)
initialize_pickle_file_from_reduce("urllib_request_urlopen.pkl", reduce_urllib_request_urlopen)
initialize_pickle_file_from_reduce("logging_FileHandler.pkl", reduce_logging_FileHandler)

# types.CodeType can construct arbitrary code objects - using raw opcodes since CodeType can't be pickled directly
initialize_data_file(
Expand Down
2 changes: 2 additions & 0 deletions tests/test_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ def test_scan_file_path():
)
assert_scan("io_FileIO.pkl", [Global("_io", "FileIO", SafetyLevel.Dangerous)])
assert_scan("urllib_request_urlopen.pkl", [Global("urllib.request", "urlopen", SafetyLevel.Dangerous)])
# logging.FileHandler can create arbitrary files on the filesystem
assert_scan("logging_FileHandler.pkl", [Global("logging", "FileHandler", SafetyLevel.Dangerous)])
# types.CodeType can construct arbitrary code objects for execution
assert_scan("types_CodeType.pkl", [Global("types", "CodeType", SafetyLevel.Dangerous)])
# cloudpickle uses _make_function and _builtin_type with CodeType to reconstruct arbitrary callables
Expand Down
Loading