FS#22991 - Protect users against zip bombs.

Attached to Project: AUR web interface
Opened by Loui Chang (louipc) - Monday, 21 February 2011, 16:11 GMT
Last edited by Lukas Fleischer (lfleischer) - Wednesday, 09 March 2011, 17:13 GMT
Task Type Feature Request
Category Backend
Status Closed
Assigned To Lukas Fleischer (lfleischer)
Architecture All
Severity Low
Priority Normal
Reported Version 1.7.0
Due in Version 1.8.1
Due Date Undecided
Percent Complete 100%
Votes 1
Private No

Details

Use xz -l or gunzip -l functionality to reject packages over a certain configurable size.
This task depends upon

Closed by  Lukas Fleischer (lfleischer)
Wednesday, 09 March 2011, 17:13 GMT
Reason for closing:  Implemented
Additional comments about closing:  Implemented in 1.8.1.
Comment by Lukas Fleischer (lfleischer) - Monday, 21 February 2011, 19:46 GMT
We can also access the uncompressed size of a gzip'ed file directly via PHP (it's like 4-5 lines of code). The problem is that the size is only stored in a 4 byte integer, so it's actually the uncompressed size modulo 2^32. Just tested that with `dd if=/dev/zero bs=1048576 count=4096 of=foo; gzip foo`. After that, `gzip -l foo` reports a uncompressed size of 0 bytes and a compression ratio of 0%.

That means our check will be easy to bypass by just using source files with a total size of 2^32 * m + n (m being a natural number and n being very small).
Comment by Loui Chang (louipc) - Monday, 21 February 2011, 23:22 GMT
So we have a few red flags we can look for:
* Uncompressed size zero.
* Compressed size significantly larger than uncompressed size.
* Compression ratio less than or equal to zero.
Comment by Lukas Fleischer (lfleischer) - Tuesday, 22 February 2011, 09:12 GMT
Well... I noticed that my 4GiB test file has a compressed size of about 4.0MiB. As it's only a bunch of 0-bytes from "/dev/zero", my guess is that DEFLATE has a best case compression ratio of about 1/1000 (haven't proved that). So how about just having two settings "$MAX_FILESIZE" and "$MAX_FILESIZE_UNCOMPRESSED" and setting "$MAX_FILESIZE" to something below 2-3MiB? That way, we could really ensure that there won't be any source packages that have a uncompressed size of more than "$MAX_FILESIZE_UNCOMPRESSED" (keeping that value below 4GiB, of course) without using any weird heuristics.

I also traversed the whole incoming package directory of our official AUR setup and there isn't a single tarball that's bigger than 2MiB, so that should be fine.
Comment by Cedric Girard (Xdark) - Tuesday, 22 February 2011, 09:47 GMT
Yes, the red flags Loui spoke of are not enough:
"dd if=/dev/zero bs=1048576 count=4100 of=foo; gzip foo"
gives:
compressed uncompressed ratio uncompressed_name
4172243 4194304 0.5% foo
We have a 4MB compressed archive with an apparent uncompressed size slightly larger and thus a compression ratio above zero.
Comment by Cedric Girard (Xdark) - Tuesday, 22 February 2011, 10:21 GMT
What about doing something like "gunzip -c" piped into a dd with a count of the compressed size? If the compressed file is a "normal" file, it will works fine. If the compressed file is malicious, it will be limited to a reasonable size (configurable).
Comment by Lukas Fleischer (lfleischer) - Tuesday, 22 February 2011, 10:36 GMT
Xdark: Uncompressing parts of the tarball would be vulnerable to DoS, again. I think having both compressed and uncompressed file size limits is the best way to go.
Comment by Lukas Fleischer (lfleischer) - Tuesday, 22 February 2011, 11:28 GMT
I noticed that "upload_max_filesize" defaults to "2M" for current PHP releases, so it might be sufficient to have a uncompressed file size limit in "web/lib/config.inc" and some comment about keeping "upload_max_filesize" below 3MiB to have real protection. Any objections?
Comment by Lukas Fleischer (lfleischer) - Tuesday, 22 February 2011, 11:33 GMT
Any suggestions for a reasonable uncompressed file size limit? 4MiB? 8MiB? 32MiB? 128MiB?
Comment by Lukas Fleischer (lfleischer) - Wednesday, 23 February 2011, 10:26 GMT
  • Field changed: Due in Version (Undecided → 1.9.0)

Loading...