Bug 58499

Summary: ZipSecureFile throws zip bomb detected
Product: POI Reporter: Mirek <M.Hankus>
Component: SXSSFAssignee: POI Developers List <dev>
Status: RESOLVED FIXED    
Severity: major    
Priority: P2    
Version: 3.13-dev   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Bug Depends on:    
Bug Blocks: 59743    

Description Mirek 2015-10-16 12:06:23 UTC
When using 3.13 SXSSFWorkbook fails with exception

java.io.IOException: Zip bomb detected! The file would exceed certain limits which usually indicate that the file is used to inflate memory usage and thus could pose a security risk. You can adjust these limits via setMinInflateRatio() and setMaxEntrySize() if you need to work with files which exceed these limits. Counter: 408576, cis.counter: 4080, ratio: 0.009985902255639098Limits: MIN_INFLATE_RATIO: 0.01, MAX_ENTRY_SIZE: 4294967295



Problem is that SXSSFWorkbook.write creates template file. 

File tmplFile = TempFile.createTempFile("poi-sxssf-template", ".xlsx")


in my case it looks like 

-rw-r--r--. 1 root root     7095 10-16 14:00 poi-sxssf-template5548165903088413476.xlsx

when uncompressed this file produces 1085244 bytes of content, so compresscion ratio is 0.0065377002 - exception is thrown with MIN_INFLATE_RATIO: 0.01, so this template file cannot be read by POI (which later inject data into this file). 

I'm marking this bug with severity major, because 3.13 is not able to produce SXSSF workbooks.
Comment 1 Andreas Beeker 2015-10-16 15:14:46 UTC
The content of your sxssf seems to be a lot of repeating content.
Why don't you want to change the min inflation ratio?

Btw. I haven't understood why you use SXSSF first and then load it again via XSSF and inject data ...

Andi.
Comment 2 Dominik Stadler 2015-10-16 15:50:34 UTC
Also can you provide some sample code which reproduces the problem?

And as Andi suggested, something like a ZipSecureFile.setMinInflationRatio(0.00000001) may make it work.
Comment 3 Mirek 2015-10-16 17:42:26 UTC
Sorry - I was mistaken with root cause. My problem can be reproduced with such test


try (OutputStream os = new NullOutputStream()) {
            SXSSFWorkbook workbook = new SXSSFWorkbook();
            Sheet sheet = workbook.createSheet();
            for (int i = 0; i < 900; i++) {
                Row r = sheet.createRow(i);
                Cell c = r.createCell(0);
                CellStyle cs = workbook.createCellStyle();
                c.setCellStyle(cs);
                c.setCellValue("AAA");                
            }
            workbook.write(os);
            workbook.dispose();
}


This code will throw zip bomb exception.  Adding ZipSecureFile.setMinInflationRatio(0) eliminates this problem. You can close this issue.
Comment 4 Dominik Stadler 2015-10-17 14:45:07 UTC
I have added some improvements on this in r1709180, we now do not run these "zip-bomb" checks for rather small files now to avoid such false-positives, this should make this very simple case work now. Unit-tests have been added to verify that it stays fixed. Also the error message should indicate slightly better how to work around the error message.
Comment 5 Axel Howind 2016-06-20 09:49:50 UTC
I think the check should only be done when reading a workbook but never when writing. Since in the example code no workbook is read, the problem seems to be that the streaming API writes to a temp file and reads that back in again.

I just got hot by this problem, and the suggested fix to adjust the limit by calling ZipSecureFile.setMinInflateRation() does not seem appropriate since it is a global setting and thus would make applications that both read and write workbooks less secure.

I have not checked the POI code yet, but I'd suggest better not using ZipSecureFile when *writing* workbooks (or in this case: reading back the temporary files created when writing an instance of SXSSFWorkbook).

Would such a patch be accepted?
Comment 6 Javen O'Neal 2016-06-20 10:15:40 UTC
The main purpose of the zip bomb detection is to safely handle untrusted input. Since a workbook that has already been fully read into memory has passed the safety test, I suppose you could consider it quasi-safe with regard to writing it back out.

If you can't think of a way that a latent zip bomb could unwrap itself while writing the workbook that wasn't a result of poor (trusted) code, then I would agree with removing this limit when writing.

Not being a security expert, the safer option is to set different read and write limits.

Let's continue the discussion on the POI dev mailing dev@poi.apache.org.