unsafe unzip with spring

Posted by tetley at 2020-04-12

For cve-2018-1263, see patch analysis.

Start with simple test code: is a malicious compressed package, with the structure as follows:

Unziptransformer.setworkdirectory (path); set the unzip directory as the here folder under the current directory under normal circumstances. As shown in GIF above, good.txt is generated in the here folder. However, evil.txt escaped this restriction and was generated under G: / / tmp.


See the annex for the source code related to environment. In order to replicate the vulnerability, you need to create a TMP directory under the root directory of the hard disk. is in cve-2018-1261 \ SRC \ main \ resources.

Trace the code, and put a breakpoint at unziptransformer. Transform (evilmessage); to follow. When the control flow reaches org / springframework / integration / zip / transformer / 112


Here, InputStream will be input and zipentrycallback will be used as the callback function. Follow iterate to org / zeroturnaround / zip /

ZipEntryCallback iterate

In iterate, the zipinputstream object in is generated through in = new zipinputstream (New bufferedinputstream (is)); after that, the entries in the object in are obtained through in. Getnextentry(). For getnextentry(), it will directly print out the directory. For details, see stackoverflow: how does zipinputstream. Getnextentry() work?. So for

in = new ZipInputStream(new BufferedInputStream(is)); in in.getNextEntry() getNextEntry()

Back to

It can be seen that the value of entry is.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. / TMP / evil.txt.

entry ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/evil.txt

After that, call the callback function process:.

Tempdir is a temporary generated folder, and zipentryname is obtained through zipentry. Getname(), which is a string of.. /.. /.. /. Then determine the decompression directory through the final file destinationfile = new file (tempdir, zipentryname); it is here that causes the cross directory vulnerability. Next, call copy to write the data to the destinationfile.

tempDir zipEntryName zipEntry.getName() ../../../ final File destinationFile = new File(tempDir, zipEntryName); copy

The reason for this is that for getnextentry, TMP is just the name of the directory, while for copy operation, TMP is interpreted as directory crossing operation, resulting in arbitrary decompression.

../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp ../../../

The patch disallow traversal entity in zip in 1.0.1.release mainly checks the zipentryname before the copy operation

For malicious compressed packets, after the destinationfile is generated, assume the value is. \ here \ e401f4b8-0ecb-3f3a-76ce-5318b14d6000 \.. \.. \ TMP \ evil.txt. When calling destinationfile. Getcanonicalpath(), resolve `. And.. to the corresponding correct path, and obtain its normalized absolute path. Then compare it with the working directory workdirectory. Getcanonicalpath() to determine whether directory traversal exists.

destinationFile .\here\e401f4b8-0ecb-3f3a-76ce-5318b14d6000\..\..\tmp\evil.txt destinationFile.getCanonicalPath() `. .. workDirectory.getCanonicalPath()

After that, on May 11, 2018, pivotal released another announcement:

The reasons are:

While the framework itself now does not write such files, it does present the errant path to the user application, which could inadvertently write the file using that path.

That is to say, the generated destinationfile is actually wrong. Although the framework itself will not have problems and will not have directory traversal vulnerabilities, for applications, it may directly use the path of destinationfile to operate and cause errors later. Therefore, in the patch in version 1.0.2.release [dissallow traversal entry even for byte [], the following checks are made directly when generating the destinationfile:

destinationFile destinationFile destinationFile

In addition, in remove unnecessary check for the.

.. zipEntryName.contains("..")

Similar compressed file directory traversal vulnerabilities have appeared before, to name a few.