Bug#306693: cpio: allows extracting insecure pathnames (leading slash = / and dotdot = ..)

2005-05-21 Thread t takahashi
Tags: security
Severity: grave



Bug#306693: cpio: allows extracting insecure pathnames (leading slash = / and dotdot = ..)

2005-04-28 Thread t takahashi
severity: important

After looking at the severities of other cpio bug reports that have
been around for hundreds of days, I concluded that this should be
important instead of normal.



Bug#306693: cpio: allows extracting insecure pathnames (leading slash = / and dotdot = ..)

2005-04-28 Thread t takahashi
tags: security

The docs suggest grave or critical for security bugs, but I'm not sure
whether that is appropriate.



Bug#306693: cpio: allows extracting insecure pathnames (leading slash = / and dotdot = ..)

2005-04-27 Thread gambarimasu+reportbug
Package: cpio
Version: 2.5-1.2
Severity: normal


Hi,

OK, several related issues here.  You probably already see where I am
going, but please humor me for a minute just in case.  Not sure if I'm
supposed to file with debian or with cpio's own bug lair.

I believe (IMHO) that this is a security issue and should be fixed
soon.  Anybody can create an archive and put it on the net that lots
of trusting people will run cpio -i on to inadvertently write a file
in, say, /etc/cron.daily.

~# touch /etc/cron.daily/aaa
~# find /etc/cron.daily/aaa|cpio -oa.cpio
1 block
~# \rm -v /etc/cron.daily/aaa 
removed `/etc/cron.daily/aaa'

Imagine that that file is buried deep in a huge archive of files with
innocent relative pathnames, and was made executable first.  Now the
unsuspecting user (who should, but does not, know better), does this:

~# cpio -t  a.cpio 
 lots of innocent files
/etc/cron.daily/aaa
 lots of innocent files
1 block
~# cpio -i  a.cpio #oops, forgot an option
1 block

And does not do this:

~# ls -l /etc/cron.daily/aaa 
-rw---  1 root root 0 Apr 27 18:23 /etc/cron.daily/aaa
~# \rm -v /etc/cron.daily/aaa
removed `/etc/cron.daily/aaa'

Note that the user should have used the --no-absolute-filenames
option, but did not.  So you could say it's preventable.  But consider
what happens if the pathname is relative:

~# find ../../../../../../../../../../../../etc/cron.daily/aaa | cpio -oa.cpio

Now that option will not help.  To prevent that requires preprocessing
the archive with cpio -t and grep '\.\.'.  How many users do that?
Especially on a large archive?

OK, here are my comments:

First, there is no way that I know of within cpio -o to prohibit
absolute pathnames and .. in a pathname.  This is important to flag
mistakes in the input and to prevent somebody who runs cpio -i
(including unfixed versions of cpio) from inadvertently installing
your files in unexpected (i.e. not below pwd) places.  IMHO safety
should be the default, but an option would be OK if necessary.
Prohibiting ^/ and \.\. is easy in a shell, but it should be built in
to make error handling easier.  Of course, this doesn't solve the
security problem.  It just avoids mistakes.

Second, more importantly, cpio -o does not by default prohibit
absolute filenames.  The option --no-absolute-filenames is an OK
workaround, but IMHO it should be the default.

Third, even more importantly, cpio -o does not by default or via an
option appear to check for .. in pathnames.  Using .. in the archive
is rarely needed, and IMHO it should be disallowed by default.  At
least, it should be an option.  (If it is disallowed by default, a nop
option to disallow should probably still be provided so that other
versions of cpio will (ideally) balk at an unrecognized option,
tipping the user to be more careful.)

Finally, I have a related wishlist item, which is an option to cpio -o
archives in which all pathnames, whether relative or absolute, are
converted to fully canonical (but NOT symlink-dereferenced unless -L
is used) relativized absolute pathnames.  By this I mean that cpio -o
with this option should canonicalize relative paths into absolute
paths, but remove the leading / (except for /, of course).  This
ensures best safety for unsuspecting cpio -i users, and is a commonly
needed uniform format.

It might be argued that --canonical should be up to the pipeline that
calls cpio -o, but in practice, getting these safety and security
issues right in all cases, including when NULs delimit files, and
including portability concerns, is nontrivial.

I am aware that these issues often apply to other archivers also, but
have not filed reports there.  Over the years they have slowly been
addressing some of them, but not all of them.

I'd like a CC:/BCC: on any and all discussion about this topic, if
possible.

Thanks.  And thanks for cpio; it is my favorite archiver.

gmail ! gambarimasu+reportbug

P.S.  There is another can of worms, which I won't open (much) for
symlinks (e.g. the -L option) and ancillary issues like overwriting of
existing files, trailing slash, and the known issue of what to do for
directories that come after the files in the directories.  For
example, normally we want symlinks not to be dereferenced, so
canonicalizing .. must not also do that by default.  People want a
variety of things here, so the more orthogonality the better.  For
example, most of the time we want /home/me/mysymlink/mydir/myfile to
be archived with the mysymlink intact, and /home/me/mysymlink to be
archived simply as a symlink, but some people might want defined (in
the man page) behavior for trailing slash, such as archiving the
referent if there is a trailing slash.  Of course, it would be nice if
find had options to control some of these things without preprocessing
of the command line and postprocessing of the output.  Overall, I
would like to see a bit more documentation in the cpio man page that
defines what happens if, e.g. a non-writable dir 

Bug#306693: cpio: allows extracting insecure pathnames (leading slash = / and dotdot = ..)

2005-04-27 Thread t takahashi
P.P.S.  I found a more subtle security hole.  It is even more dangerous.

/tmp/aaa$ mkdir ../b
/tmp/aaa$ ln -s ../b b
/tmp/aaa$ touch ../b/trojan
/tmp/aaa$ ls b
trojan
/tmp/aaa$ find b b/trojan
b
b/trojan
/tmp/aaa$ find b b/trojan | cpio -o  dangerous
cpio: b: truncating inode number
cpio: b/trojan: truncating inode number
1 block
/tmp/aaa$ /bin/rm -v b/trojan b
removed `b/trojan'
removed `b'
/tmp/aaa$ ls
dangerous
/tmp/aaa$ cpio -tdangerous 
b
b/trojan
1 block
/tmp/aaa$ cpio -vtdangerous 
lrwxrwxrwx   1 kpc  kpc 4 Apr 27 19:46 b - ../b
-rw---   1 kpc  kpc 0 Apr 27 19:46 b/trojan
1 block

Notice that grep '\.\.' on the output of cpio -t would not find the
relative pathname.  You have to use cpio -vt.  Now watch this:

/tmp/aaa$ cpio -idangerous 
1 block
/tmp/aaa$ ls
b  dangerous
/tmp/aaa$ ls ../b
trojan

IMHO cpio should disallow this by default.  Imagine
../../../../../../../etc/cron.daily again.  cpio should check for
extracting in directories that are not below pwd, even if it is via
indirect means such as a symlink.

Wow!