-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OmegaConf is vulenrable to ddos via specially crafted yaml input (billion laughs attack) #794
Comments
I like option 3; it feels safer and easier to implement than 1 and 2. R.e. option 1:
# lol_attack.py
lol1 = "lol"
lol2 = [lol1, lol1, lol1, lol1, lol1, lol1, lol1, lol1, lol1]
lol3 = [lol2, lol2, lol2, lol2, lol2, lol2, lol2, lol2, lol2]
lol4 = [lol3, lol3, lol3, lol3, lol3, lol3, lol3, lol3, lol3]
lol5 = [lol4, lol4, lol4, lol4, lol4, lol4, lol4, lol4, lol4]
lol6 = [lol5, lol5, lol5, lol5, lol5, lol5, lol5, lol5, lol5]
lol7 = [lol6, lol6, lol6, lol6, lol6, lol6, lol6, lol6, lol6]
lol8 = [lol7, lol7, lol7, lol7, lol7, lol7, lol7, lol7, lol7]
lol9 = [lol8, lol8, lol8, lol8, lol8, lol8, lol8, lol8, lol8]
lol10 = [lol9, lol9, lol9, lol9, lol9, lol9, lol9, lol9, lol9]
# The below lines will fill up computer memory:
# from omegaconf import OmegaConf
# cfg = OmegaConf.create(lol10) R.e. option 2: Still vulnerable if the user calls |
The problem with having a hard limit on number of nodes is that it could break for legitimate use cases suddenly based on user input. 4 is also interesting. Maybe have a static function for setting anchors policy and have it reject them by default. (detected by seeing the same object in the dictionary). something like: Where the page would indicate that anchors are inferior because they don't work cross files and are vulnerable to this attack and suggest converting to interpolations, or, as an alternative - disable the check vis something like OmegaConf.enable_unsafe_anchors(true). |
So the idea is to introduce some global state that keeps track of the current policy, right? Or perhaps the user could set a flag |
Yes. class AnchorsPolicy(Enum):
# Reject anchors, allow for header to change behavior. Default behavior
HEADER = 1
# Always allow anchors
UNSAFE = 2
# Never allow anchors. Reject anchors even in file header attempts to enable it.
RESTRICTED = 3
OmegaConf.setAnchorsPolicy(policy: AnchorsPolicy) |
OmegaConf is vulnerable to Billion laughs attack.
Specially crafted yaml input files can use yaml anchors to create a yaml input that is fast to load but very slow to traverse because it contains billions of nodes.
This is considered medium priority and will be addressed in a future major version of OmegaConf.
Most potential fixes are breaking.
Details
pyyaml is creating references to the same object when it loads an anchor, which is why it can do load such files quickly.
Example input:
Such input creates billions of yaml nodes. OmegaConf will take an unreasonably long time to instantiate an object from it.
User-land solutions
1. Use interpolations instead of yaml anchors
Avoid yaml anchors and use interpolations instead.
The following config uses interpolations to achieve a similar behavior:
Note that the config is still too big for actual traversal but since it's evaluated lazily it's possible to use it if it's done carefully.
2. Validate object created by pyyaml
If the config cannot be trusted, a check can be made before instantiating OmegaConf from a dict (instead of from a file) with a function similar to this:
Possible future OmegaConf solutions
The following are possible strategies to handle it inside OmegaConf.
The text was updated successfully, but these errors were encountered: