-
Notifications
You must be signed in to change notification settings - Fork 297
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
FIX: Zip slip directory traversal vulnerability in file handling functions #884
base: master
Are you sure you want to change the base?
Conversation
Added a condition to check if self.conf is of type None
invesalius/gui/preferences.py
Outdated
self.conf = self.session.GetConfig("mep_configuration") | ||
if self.conf is None: | ||
self.conf = {} | ||
else: | ||
self.conf = dict(self.conf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here it's better to use a try except:
try:
self.conf = dict(self.session.GetConfig("mep_configuration"))
except TypeError:
self.conf = {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's better to remove this from this PR and make the change in #837 PR
invesalius/project.py
Outdated
fname = os.path.join(folder, decode(t.name, "utf-8")) | ||
fname = os.path.normpath(fname) | ||
if not os.path.commonprefix( | ||
[os.path.abspath(folder), os.path.abspath(fname)] | ||
) == os.path.abspath(folder): | ||
raise Exception(f"Directory traversal detected: {t.name}") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using tar_filter
for avoid this type of problem. But it only works for python >= 3.12. Can you implement our own tar_filter
if tar_filter
is None.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tfmoraes Can you please review if this is the custom tar_filter
you meant? It implements the custom filter if getattr(tarfile, "tar_filter", custom_tar_filter)
returns None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that is the idea. I didn't tested yet. Also, I think it's better to put custom_tar_filter as normal function, not inside a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't keeping the custom_tar_filter within the scope of Extract() be cleaner? Unless and until it's reused for other stuff in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tfmoraes I have added put custom_tar_filter
as a normal function outside Extract()
. Also added a an ErrorMessageBox
popup on directory traversal detection. I have also run test on the code to verify its working fine.
I am attaching the python scripts to reproduce a directory traversal attempt:
import os
import tarfile
import shutil
def create_zip_slip(original_tar_path, output_tar_path, malfile_name, file_cont):
if not os.path.exists(output_tar_path):
with tarfile.open(output_tar_path, mode='w') as tar:
pass
shutil.copy2(original_tar_path, output_tar_path)
with tarfile.open(output_tar_path, mode='a') as tar:
malfile_path = os.path.join("../../../../../../../../../../../../../../", malfile_name)
with open(malfile_name, 'w') as f:
f.write(file_cont)
tar.add(malfile_name, arcname=malfile_path)
os.remove(malfile_name)
print(f"Zip Slip vulnerable tar file created at: {output_tar_path}")
original_tar_path = 'original.inv3'
output_tar_path = 'vulnerable.inv3'
malfile_name = 'malicious.txt'
file_cont = 'This is a malicious file!'
create_zip_slip(original_tar_path, output_tar_path, malfile_name, file_cont)
Replace "original.inv3" with any actual Invesalius project file and then try opening vulnerable.inv3
Added Error pop-up when malicious file is detected Generated malicious .inv3 file and ran tests
This fixes issue #882
The "Zip Slip" vulnerability occurs when an application extracts files from an archive without validating their paths, allowing attackers to overwrite arbitrary files on the system.
To fix this I checked the following:
I added method to Sanitize the paths before use in
Compress
andExtract
functions. It ensures ensures that any unexpected directory traversal attempts (such as ../) or adding files to unwanted locations are handled correctly.Please review this PR @tfmoraes @paulojamorim @paulojamorim @henrikkauppi @rmatsuda