Hi, Looking at cpio, i found what seems to be a way to bypass the --no-absolute-filenames option, which supposedly prevents data to be written outside of the current folder.
One just need to create a cpio archive that contains a symlink to the required destination, then a file that appears to be from inside the symlink (this requires a specially crafted cpio archive) : 1) there is no file called /tmp/blah [cedric@x201 testings]$ ll total 4 -rw-rw-r--. 1 cedric cedric 384 Jun 4 22:34 link.cpio [cedric@x201 testings]$ ll /tmp/blah ls: cannot access '/tmp/blah': No such file or directory 2) I extract the specially crafted cpio [cedric@x201 testings]$ cpio -idv --no-absolute-filenames < link.cpio link link/blah 1 block 3) there is a file /tmp/blah [cedric@x201 testings]$ ll total 4 lrwxrwxrwx. 1 cedric cedric 5 Jun 4 22:21 link -> /tmp/ -rw-rw-r--. 1 cedric cedric 384 Jun 4 22:15 link.cpio [cedric@x201 testings]$ ll /tmp/blah -rw-rw-r--. 1 cedric cedric 3 Jun 4 22:21 /tmp/blah The very naive patch attached makes use of safer_name_suffix() to sanitize symlink's value. Thanks! -- Cedric Buissart, Product Security
diff --git a/src/copyin.c b/src/copyin.c index ba887ae..38ca70e 100644 --- a/src/copyin.c +++ b/src/copyin.c @@ -645,6 +645,7 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_file_des) link_name = xstrdup (file_hdr->c_tar_linkname); } + cpio_safer_name_suffix (link_name, false, !no_abs_paths_flag, false); res = UMASKED_SYMLINK (link_name, file_hdr->c_name, file_hdr->c_mode); if (res < 0 && create_dir_flag)