Proper defense against symlink attacks in tar, unzip et al
Harald van Dijk
harald at gigawatt.nl
Mon Feb 19 16:09:00 UTC 2018
On 19/02/2018 15:47, Denys Vlasenko wrote:
>>> Let's also brainstorm option 3:
>>> Allow symlinks which
>>> (a) start with one or more "../";
>>> (b) never end up on a higher level of directory tree:
>>> "../dir/.." is ok,
>>> "../../usr/bin/.." is ok,
>>> "../file" is not ok,
>>> "../../dir/file" is not ok;
>>> and (c) they also should not leave tarred tree:
>>> symlink "sbin/mkswap" to "../bin/busybox" is ok, but
>>> symlink "mkswap" to "../bin/busybox" is not ok (it hops "above" the tree).
>>>
>>> This sounds a bit complicated, but it can be achieved just by looking
>>> at names, no multiple lstat() calls for every open() needed.
>>>
>>> With only these symlinks allowed, we know that if we untar to an empty
>>> directory or to a formerly empty directory with another tarball
>>> untarred, any pathname we open, whilst it can contain components which
>>> are symlinks, they nevertheless can not allow new opens to "leave" the
>>> tree and create files elsewhere.
>>
>>
>> This wouldn't be safe, I think. Consider a tarball containing
>>
>> a/
>> b/
>> a/a -> ../b
>> a/a/a -> ../../c
>
> The link to "../../c" is not allowed - it fails criteria (b).
You wrote "it can be achieved just by looking at names", but that's not
enough here: you have to know that a/a/a is actually b/a, so only one
level deep in the -C directory, to know that ../../c points outside the
-C directory. Since the a/a -> ../b symlink may not even be in this
archive, the only way to determine that is by lstat().
Cheers,
Harald van Dijk
More information about the busybox
mailing list