-
Notifications
You must be signed in to change notification settings - Fork 312
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
Validate entry sizes when extracting #403
Conversation
@jdleesmiller looks ok. The only thing that we need to show some notification on unsecured behavior. |
I think this looks OK too. Minor question though: There looks to be changes unrelated to this PR in the README. Headers and text moved around. Also, it should definitely have a minor version bump, but maybe it should be a major bump. Do we have a feel for how much code out there might suddenly start failing unexpectedly? One strategy might be to release it as a minor bump with |
Thanks both for the quick turnaround!
Could you elaborate on what you have in mind here? At the moment it will throw an error if the file's reported uncompressed size is incorrect.
I reorganised the README for other options, because I thought the list was getting too long as I added yet another one. The content of the sections about the existing options should all be unchanged.
Nothing very precise... but I have been using the Your suggestion of defaulting |
067aef2
to
7849f73
Compare
Rebased onto latest master and updated according to comments above (default false in 1.3). |
@jdleesmiller notify into stdout need to show that there was such zip file. For cases when check is disabled - so instead of raising it will be a warning. |
Sorry to be a pain. Could we use (I realise that there are other parts of the library code that use |
Right... that would be better, but unfortunately I used |
👍 good for me! I'll work something up in the next couple of weeks... |
OK, thanks! In that case I will get this merged and release 1.3. |
unning bundle-audit to check for insecure dependencies... Updating ruby-advisory-db ... From https://github.com/rubysec/ruby-advisory-db * branch master -> FETCH_HEAD Already up to date. Updated ruby-advisory-db ruby-advisory-db: 406 advisories Name: rubyzip Version: 1.2.3 Advisory: CVE-2019-16892 Criticality: Unknown URL: rubyzip/rubyzip#403 Title: Denial of Service in rubyzip ("zip bombs") Solution: upgrade to >= 1.3.0 Vulnerabilities found! Failed. Security vulnerabilities were found.
Name: rubyzip Version: 1.2.2 Advisory: CVE-2019-16892 Criticality: Unknown URL: rubyzip/rubyzip#403 Title: Denial of Service in rubyzip ("zip bombs") Solution: upgrade to >= 1.3.0
Update (2019-09-25): Assigned CVE-2019-16892
To extract zip files safely:
If you upgrade to rubyzip >= 1.3.0 and < 2.0.0, you must:
entry.size
as illustrated in the README before you callentry.extract
, andZip.validate_entry_sizes = true
to enable the validation added in this PR.If you upgrade to rubyzip >= 2.0.0, you must:
entry.size
as illustrated in the README before you callentry.extract
.If you are using a recent (not EOL) version of ruby, the upgrade to 2.0.0 should be smooth. See the Changelog for details.
Fix #193 ("Protection Against Zip Bombs")
Currently there is no way to safely check how much data the
Zip::Entry#extract
method will actually extract, because the uncompressed size reported in the zip can be spoofed, and the extraction happens in the method where the caller can't check on its progress.This can lead to denial of service through disk exhaustion if the input is a zip bomb.
Approach
The approach taken here is based on the
validateEntrySizes
option for node's yauzl unzipping library: rubyzip can check that it doesn't extract (much) more than the expected amount of data, based on the uncompressed size reported in the zip file. That way the caller can check the entry's uncompressed size before extracting and trust that it is not misleading.The "much" in "much more" above is because rubyzip writes the data in chunks (currently 32KiB), and it may write up to one chunk more than expected, but that should be negligible, and there will be an error that signals that rubyzip wrote more data than expected.
Impact
Zip files with incorrectly reported uncompressed sizes that worked before will now fail with a
Zip::EntrySizeError
. Like inyauzl
, the safe behaviour is the default but a flag is provided to allow the caller to (dangerously) skip the checks:EDIT: Following discussion below,
false
will be the default in the 1.3 release. We'll default totrue
in 2.0.I have updated the README to say that the caller should be checking the size before extracting. I also reorganised some of the options, since there are now quite a few.
Review
I will aim to leave this open for 1 week for review. CC @simonoff @olleolleolle @hainesr who have been active recently.
It probably merits at least a minor version bump.
Credit
Thanks to the GE Digital Cyber Security Team for providing a proof of concept, which was the basis for the test case.
Thanks to @thejoshwolfe for providing (I think) a good example of how to handle this, in
yauzl
.