Bug 8411 - tar: directory traversal via crafted tar file which contains a symlink pointing outside of the current directory
Summary: tar: directory traversal via crafted tar file which contains a symlink pointi...
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Other (show other bugs)
Version: unspecified
Hardware: PC Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-20 00:29 UTC by Tyler Hicks
Modified: 2018-02-20 15:08 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:


Attachments
Patch for busybox 1.22.0 (4.39 KB, patch)
2015-11-05 16:33 UTC, Chris Lamb (lamby)
Details
Patch for busybox 1.22.0 v2 (4.38 KB, text/plain)
2015-11-05 16:38 UTC, Chris Lamb (lamby)
Details
Patch for busybox 1.22.0 v3 (4.39 KB, text/plain)
2015-11-05 16:46 UTC, Chris Lamb (lamby)
Details
Patch for busybox 1.22.0 v4 (5.89 KB, patch)
2015-11-09 22:26 UTC, Chris Lamb (lamby)
Details
Patch for busybox 1.22.0 v5 (4.44 KB, patch)
2015-11-09 23:29 UTC, Chris Lamb (lamby)
Details
Tar file containing two files (abs and rel) encoded as hardlinks of /tmp/foo (2.00 KB, application/x-tar)
2015-11-10 00:58 UTC, Tyler Hicks
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tyler Hicks 2015-10-20 00:29:11 UTC
It was discovered that busybox's tar implementation will extract a symlink that points outside of the current working directory and follow that symlink when extracting other files. This allows for a directory traversal attack when extracting untrusted tarballs.

This behavior is documented in the source code:

  http://git.busybox.net/busybox/tree/archival/tar.c#n25

I took a quick look at how GNU tar handles such situations. If the symlink target is absolute or contains a ".." component, they create a regular file as a placeholder. After all other files have been extracted, the placeholder files are replaced with the originally intended symlinks.

(That is also how they handle hardlink extraction but I don't see any support for LNKTYPE files in busybox tar.)
Comment 1 Tyler Hicks 2015-10-21 21:55:41 UTC
CVE-2011-5325 was assigned to this issue:

  http://openwall.com/lists/oss-security/2015/10/21/7
Comment 2 Chris Lamb (lamby) 2015-11-05 16:33:24 UTC
Created attachment 6191 [details]
Patch for busybox 1.22.0
Comment 3 Chris Lamb (lamby) 2015-11-05 16:38:56 UTC
Created attachment 6196 [details]
Patch for busybox 1.22.0 v2

Updated patch attached - I didn't spot I had removed a TODO comment; apologies.
Comment 4 Chris Lamb (lamby) 2015-11-05 16:46:13 UTC
Created attachment 6201 [details]
Patch for busybox 1.22.0 v3

Matching code style.
Comment 5 Tyler Hicks 2015-11-07 06:06:25 UTC
(In reply to comment #4)
> Created attachment 6201 [details]
> Patch for busybox 1.22.0 v3
> 
> Matching code style.

Hello Chris - the dot dot check is incorrect. A file can still be extracted into the parent directory:

$ ln -s .. foo
$ tar -cf dotdot.tar foo
$ rm foo
$ mkdir foo
$ touch foo/bar
$ tar -rf dotdot.tar foo/bar
$ rm -rf foo
$ stat -t ../bar
stat: cannot stat ‘../bar’: No such file or directory
$ busybox tar -xvf dotdot.tar
foo
foo/bar
$ stat -t ../bar
../bar 0 0 81b4 1000 1000 fc00 23736439 1 0 0 1446875494 1446875494 1446876258 0 4096
Comment 6 Chris Lamb (lamby) 2015-11-09 22:26:06 UTC
Created attachment 6206 [details]
Patch for busybox 1.22.0 v4

Oh, good catch.

Instead of matching ".." anywhere ("..foo" is totally valid after all!), I'm also now just matching on a literal ".."
Comment 7 Tyler Hicks 2015-11-09 23:21:47 UTC
(In reply to comment #6)
> Created attachment 6206 [details]
> Patch for busybox 1.22.0 v4
> 
> Oh, good catch.
> 
> Instead of matching ".." anywhere ("..foo" is totally valid after all!), I'm
> also now just matching on a literal ".."

Something odd happened with the patch that you attached. It is base64 encoded and, while it does contain some changes, does not contain the change to match a lateral ".." sequence.
Comment 8 Chris Lamb (lamby) 2015-11-09 23:29:00 UTC
Created attachment 6211 [details]
Patch for busybox 1.22.0 v5

That's.. odd. Let's try again.
Comment 9 Tyler Hicks 2015-11-10 00:26:27 UTC
(In reply to comment #6)
> Created attachment 6206 [details]
> Patch for busybox 1.22.0 v4
> 
> Oh, good catch.
> 
> Instead of matching ".." anywhere ("..foo" is totally valid after all!), I'm
> also now just matching on a literal ".."

Good point regarding "..foo". I guess that means that strstr(file_header->link_target, "../") will unintentionally match a target of "foo../bar".
Comment 10 Chris Lamb (lamby) 2015-11-10 00:45:56 UTC
> Good point regarding "..foo". I guess that means that
> strstr(file_header->link_target, "../") will unintentionally match a target of
> "foo../bar".

Doh. Although an aside, inadventent matching is "harmless" as it will end up as symlink just as intended.. but via the placeholder mechanism first. :)

Will update patch tomorrow (UTC+0) with a fresh head.
Comment 11 Tyler Hicks 2015-11-10 00:53:13 UTC
(In reply to comment #0)
> I took a quick look at how GNU tar handles such situations. If the symlink
> target is absolute or contains a ".." component, they create a regular file as
> a placeholder. After all other files have been extracted, the placeholder files
> are replaced with the originally intended symlinks.
> 
> (That is also how they handle hardlink extraction but I don't see any support
> for LNKTYPE files in busybox tar.)

I was wrong about hardlinks. They're supported in busybox's libarchive and
they're also vulnerable. From archival/libarchive/data_extract_all.c:

        /* Handle hard links separately
         * We encode hard links as regular files of size 0 with a symlink */
Comment 12 Tyler Hicks 2015-11-10 00:58:19 UTC
Created attachment 6216 [details]
Tar file containing two files (abs and rel) encoded as hardlinks of /tmp/foo

Here's a tar file that includes two files, abs and rel, that are encoded in such a way to match busybox libarchive's encoding of hardlinks (which seems to differ from what GNU tar uses).

Busybox tar will extract the two files and create them as hardlinks of /tmp/foo.

$ rm -f /tmp/foo
$ touch /tmp/foo
$ stat -c %h /tmp/foo
1
$ busybox tar -xvf hardlink.tar
abs
rel
$ stat -c %h /tmp/foo # should print "1"
3
Comment 13 Chris Lamb (lamby) 2015-12-15 14:23:04 UTC
Right, let's get this finished. What's the desired behaviour in this hardlink case? Bail out with an error?
Comment 14 Andrej Valek 2017-04-26 07:54:53 UTC
(In reply to Chris Lamb (lamby) from comment #10)
> Patch for busybox 1.22.0 v5
There is an missing closing brackets in if condition.
>if ((!strncmp(file_header->link_target, "/", 1))
> || ((!strcmp(file_header->link_target, ".."))
> || (strstr(file_header->link_target, "../"))) {
should be
if ((!strncmp(file_header->link_target, "/", 1))
 || ((!strcmp(file_header->link_target, ".."))
 || (strstr(file_header->link_target, "../")))) {

Changes have not been included in release yet.
Last change of the patch was on "2015-11-09 23:29 UTC" and currently the latest release is "10 January 2017 -- BusyBox 1.26.2 (stable)". 

My question is, if the changes are not so necessary to be upstreamed?
Comment 15 MavProxyUser 2017-07-06 17:30:44 UTC
Thanks for detailing this bug. I can now confirm that this has been exploited "in the wild" to root / jailbreak DJI Mavic, Spark, Inspire2, and Phantom 4 drone series. 

Exploit here for posterity
https://github.com/MAVProxyUser/P0VsRedHerring/blob/master/RedHerring.rb#L24

Thanks for pushing to get this patched. It has festered for a while.
Comment 16 Denys Vlasenko 2017-07-24 15:26:27 UTC
Applied patch to git:

commit b920a38dc0a87f5884444d4731a8b887b5e16018
Author: Denys Vlasenko <vda.linux@googlemail.com>
Date:   Mon Jul 24 17:20:13 2017 +0200

    tar: postpone creation of symlinks with "suspicious" targets. Closes 8411

However, I'm not sure this is sufficient to stop the attacks, if the target system is careless enough to untar untrusted tarballs. What if attacker supplies two tarballs, one creates a symlink to "/etc", and another has a lone "symlink/passwd" file? Both tarballs are not "malicious" individually. tar program can't know that unpacking second tar is doing a wrong thing!

What else needs to be done?
Comment 17 Denys Vlasenko 2017-08-10 09:57:40 UTC
Fixed in git:

commit bc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7
Author: Denys Vlasenko <vda.linux@googlemail.com>
Date:   Thu Aug 10 11:52:42 2017 +0200

    libarchive: do not extract unsafe symlinks unless $EXTRACT_UNSAFE_SYMLINKS=1
Comment 18 Denys Vlasenko 2018-02-20 15:08:55 UTC
And reverted to the "old" solution:

commit a84db18fc71d09e801df0ebca048d82e90b32c6a
Author: Denys Vlasenko <vda.linux@googlemail.com>
Date:   Tue Feb 20 15:57:45 2018 +0100

    tar,unzip: postpone creation of symlinks with "suspicious" targets

    This mostly reverts commit bc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7
    "libarchive: do not extract unsafe symlinks unless $EXTRACT_UNSAFE_SYMLINKS=1"

    Users report that it is somewhat too restrictive. See
    https://bugs.busybox.net/show_bug.cgi?id=8411

    In particular, this interferes with unpacking of busybox-based
    filesystems with links like "sbin/applet" -> "../bin/busybox".

    The change is made smaller by deleting ARCHIVE_EXTRACT_QUIET flag -
    it is unused since 2010, and removing conditionals on it
    allows commonalizing some error message codes.