Subject: Re: tar security issue VU#278501
From: Solar Designer
To: Paul Eggert
Cc: halfdog, "Dmitry V. Levin" Sergey Poznyakoff, cert-at-cert.org
Date: Sat, 28 Aug 2010 18:38:15 +0400

On Fri, Aug 27, 2010 at 04:15:07PM -0700, Paul Eggert wrote:
> My comments were about the "write example".  Sorry, I am unaware of
> this "read example".  I have received no email from CERT.

The "read example" was basically about getting an out-of-target-tree
directory into the tarball - e.g., /etc (including shadow files).

> On 08/27/2010 03:44 PM, Solar Designer wrote:
> 
> > It is unreasonable to expect the sysadmin to fully review each
> > tarball's contents before providing the data "back" to the user.
> 
> It's not unreasonable to expect the sysadmin to do a reasonable
> review; I'm not sure what is meant by "fully review", but some review
> is needed anyway, for other reasons.  For example, someone could
> hardlink /bin/su into their home directory, get it backed up, wait for
> an exploit to be discovered, then ask for the home directory
> containing the (buggy) copy of /bin/su to be restored.

Thank you for reminding me of this attack.  I recall it previously
mentioned in "why allowing arbitrary hardlinks is bad" contexts.

You've got a good point indeed, although the attack has numerous
prerequisites, and arguably it should be defeated at system level
(restricting hardlink creation to other owners' files at kernel level,
using separate filesystems, mounting /home and the like "nosuid").

It is clear to me that tar is not supposed to deal with this "hardlink
attack".  Moreover, it is also clear to me that tar is not supposed to
deal with the "hardlink variation" of Roman's attack - e.g., if a user
hardlinks /etc/shadow into their homedir, then that file will indeed be
backed up if the backups are performed as root.

This also reminds us that when such a tarball is extracted properly -
into a non-user-writable temporary tree, as root, and with proper
options to extract all metainfo that was stored - the "stolen" files'
ownership and permissions will match whatever they were before the
backup dump was created.  So the user is not actually able to read
/etc/shadow in this way.

Thus, we're in agreement thus far, which is great. :-)  Now, here's
where the "read example" attack or its variations start to differ from
the "hardlink attack":

Hardlinks are not always possible.  They may be restricted at kernel
level, with use of separate filesystems, or with parent directory
permissions to the source file.  The latter needs to be explained in
more detail, so I'll provide two real-world examples (both pertain to
lots systems currently up and running that I co-administer):

1. On Owl - our Linux distro - there's no /etc/shadow file.  Instead,
there are /etc/tcb/*/shadow files.  Permissions on /etc/tcb and
/etc/tcb/* are set such that it is not possible for a user to hardlink
any of the shadow files (even if no kernel-level restrictions are in
place and the user has a writable directory on the same filesystem).
(This was primarily done for reasons unrelated to the attacks we're
discussing now, but it illustrates my point.)

2. On systems with container-based virtualization (Virtuozzo, OpenVZ,
LXC, linux-vserver, FreeBSD jail, ...) a user (or root) in one of the
containers can't access directories outside of their container.  So they
cannot create hardlinks to such files.  Yet it is fairly common to back
such systems up in their entirety with tar running from the outside.
Of course, my advice has always been to be setting up backups for each
individual container, and it was/is done this way in some companies I am
consulting, but not in all - and without involvement from "someone like
me", it would definitely not be done that way.  It is so much simpler to
be backing up "from the outside", and it has other advantages too (e.g.,
no priority inheritance problem).  It is in fact reasonable for
sysadmins to treat containers like they treat user accounts on
multi-user systems - and indeed they don't use separate invocations of
tar per user.  If tar is mostly safe (DoS aside) to run on entire live
multi-user systems, then it ought to be similarly safe to run on entire
live multi-container system.  However, the "read example" defeats that -
allowing one to "steal" files from other containers and from the host
system - and no review by the sysadmin can reliably catch that.  Worse,
after a backup dump is extracted, the "stolen" files would actually be
readable to the attacking container's user (due to legitimately
overlapping UIDs in different containers) and root (due to root being
able to read all files in the container).

Another attack, not necessarily in the context of the specific examples
above, would be for the user to ask for a copy of a recent backup dump
of their stuff.  So they'd gain read access to stolen files via read
perms on the tarball provided to them.  Indeed, this is in part a social
engineering attack, but it relies either on the "hardlink attack" (which
can be defeated on specific systems with knowledgeable admins) or on
variations of the "read example" attack (which can't be defeated by
changes to system configuration, or at least I am not aware of
reasonable ways to do so - need to patch tar!)

> I'm not saying GNU tar can't be improved here -- far from it! -- but
> let's not give sysadmins a false sense of security.  In general, one
> cannot trust tar images created by system backups of untrusted areas.

I agree.  However, there are different kinds of trust.  Not trusting
those backup dumps for sysadmins' own use (e.g., to reuse a program
binary from a user's home directory) is essential (and it is not related
to backups procedure, but rather to the backed-up files being untrusted
in this sense from the start).

Not trusting backup dumps for restoring them "back" or for giving them
to the user is different.  This may be a requirement now (for the
reasons discussed above), but it is one that we could want to move away
from, documenting only a handful of system setup specific attacks that
would have to remain unsolved by/in tar (just the hardlink attacks?)
because they're to be defeated outside of tar.

My opinion remains that non-hardlink file stealing attacks are reasonably
unexpected by knowledgeable sysadmins (assuming proper operation of a
modern implementation of tar, which would presumably be immune from last
century's attacks on directory traversal codes - e.g., those have been
dealt with in fts(3) in *BSD and glibc at around year 2000 - I was
involved in porting the fixes to glibc's revision of the code at the time).

As to what can be done:

1. To deal with attacks via the last path component, add open() flags
such as (O_NOCTTY | O_NONBLOCK | O_NOFOLLOW) and do an fstat() checking
dev/ino against those on the directory entry (this is needed for systems
without O_NOFOLLOW) and file type.

2. To deal with attacks via non-last path components (such as Roman's
"read example"), tar could use (f)chdir() into each directory (in the
case of simple chdir() always making sure that it actually got into the
expected directory) or it could maintain directory fd's and use openat()
(preferred on systems that have it).

#1 appears to be fairly easy to implement, whereas #2 appears to require
an invasive patch (although maybe I am simply overlooking an easy way to
do it - I am not sufficiently familiar with GNU tar internals).

> > Besides, the "read example" can be used for a DoS worse than what any
> > directory traversal code is normally exposed to.
> 
> DoS attacks are out of scope here, surely.  GNU tar (or any backup
> application) can't defend against them all, or even against the
> plausible ones.

Some DoS attacks are inherent to directory traversal.  Those have to
remain and be expected.  Their impact is relatively minor (DoS against
the program itself).  Some other DoS attacks may and should be avoided,
often with just a few lines of code (see my #1 suggestion above).
Finally, the "read example" with its flipping of a non-last path
component allows for some DoS attacks that are not so trivial to
perform and not so trivial to avoid - but avoiding them happens to be
achieved with the same countermeasures as avoiding the "file stealing"
aspect of the attack.  So we should.

Indeed, that's just my opinion.

Sergey, Paul - I'd be happy if you find time and proceed to implement
the two kinds of fixes I suggested above, or indeed you may suggest
alternatives.  We may implement #1 in an Owl patch to tar, but #2 is
difficult for a non-upstream-maintainer to make and maintain as a patch,
so we're unlikely to do it on our own... even though we need a fix for
the issue.

Your help in getting this fixed will be greatly appreciated!

Thanks,

Alexander