-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
tempfile.TemporaryDirectory fails removing dir in some edge cases related to symlinks [CVE-2023-6597] #91133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
#!/usr/bin/env python3
import os
import tempfile
def createUnremovableDir(workdir):
print(workdir)
os.mkdir(f'{workdir}/mydir')
os.symlink('/bin/bash', f'{workdir}/mydir/mylink') # Symlink to a root owned file
os.chmod(f'{workdir}/mydir', 0o555)
with tempfile.TemporaryDirectory() as workdir:
createUnremovableDir(workdir) Fails because
and leaves:
This fixes it: #!/usr/bin/env python3
import os
import tempfile
def createUnremovableDir(workdir):
print(workdir)
os.mkdir(f'{workdir}/mydir')
os.symlink('/bin/bash', f'{workdir}/mydir/mylink') # Symlink to a root owned file
os.chmod(f'{workdir}/mydir', 0o555)
def _rmtree(cls, name, ignore_errors=False):
def onerror(func, path, exc_info):
if issubclass(exc_info[0], PermissionError):
def resetperms(path):
try:
if os.chflags in os.supports_follow_symlinks: # This is the patch
os.chflags(path, 0, follow_symlinks=False) # This is the patch
elif not os.path.islink(path): # This is the patch
os.chflags(path, 0)
except AttributeError:
pass
if os.chmod in os.supports_follow_symlinks: # This is the patch
os.chmod(path, 0o700, follow_symlinks=False) # This is the patch
elif not os.path.islink(path): # This is the patch
os.chmod(path, 0o700)
try:
if path != name:
resetperms(os.path.dirname(path))
resetperms(path)
try:
os.unlink(path)
# PermissionError is raised on FreeBSD for directories
except (IsADirectoryError, PermissionError):
cls._rmtree(path, ignore_errors=ignore_errors)
except FileNotFoundError:
pass
elif issubclass(exc_info[0], FileNotFoundError):
pass
else:
if not ignore_errors:
raise
shutil.rmtree(name, onerror=onerror)
# Monkey patch the class method tempfile.TemporaryDirectory._rmtree
from types import MethodType
import shutil
tempfile.TemporaryDirectory._rmtree = MethodType(_rmtree, tempfile.TemporaryDirectory)
with tempfile.TemporaryDirectory() as workdir:
createUnremovableDir(workdir) |
I think that it is a security issue which allows an unprivileged user to reset permissions of files if they can run Python program that has higher privileges. There are be special conditions for this, but perhaps you can do this by making the program to unpack a special tarfile that contains symlinks out of the tree in temporary directory. |
…-99930) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
…up (pythonGH-99930) (cherry picked from commit 81c16cd) Co-authored-by: Søren Løvborg <sorenl@unity3d.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
…n cleanup (pythonGH-99930) (cherry picked from commit 81c16cd) Co-authored-by: Søren Løvborg <sorenl@unity3d.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
…n cleanup (pythonGH-99930) (cherry picked from commit 81c16cd) Co-authored-by: Søren Løvborg <sorenl@unity3d.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: