Reputation: 3560
I need to prevent from directory traversal attack
from my code using Python. My code is below:
if request.GET.get('param') is not None and request.GET.get('param') != '':
param = request.GET.get('param')
startdir = os.path.abspath(os.curdir)
requested_path = os.path.relpath(param, startdir)
requested_path = os.path.abspath(requested_path)
print(requested_path)
tfile = open(requested_path, 'rb')
return HttpResponse(content=tfile, content_type="text/plain")
Here I need user is running like http://127.0.0.1:8000/createfile/?param=../../../../../../../../etc/passwd
this it should prevent the directory traversal attack.
Upvotes: 10
Views: 23278
Reputation: 53
a check like below will also prevent traversal.
if '..' in pathParam:
abort(ERRORCODE)
Upvotes: -3
Reputation: 25980
Suppose the user content is all located in
safe_dir = '/home/saya/server/content/'
Ending with /
is important as heinrichj mentions to ensure the check below matches against a specific directory.
You need to verify the final request is in there:
if os.path.commonprefix((os.path.realpath(requested_path),safe_dir)) != safe_dir:
#Bad user!
If the requested path is allowed to be the save_dir
itself, you would also need to allow entry if os.path.realpath(requested_path)+'/' == safe_dir
.
I encourage you to make sure all stuff you want accessible by the user in one place.
Upvotes: 16
Reputation: 7058
you could try the methods of pathlib.Path
Path(root_dir).joinpath(param).resolve().relative_to(root_dir.resolve())
should return the relative path starting from the root_dir
, or raise an ValueError
if a directory traversal attack is tried
param = 'test_file'
Path(root_dir).joinpath(param).relative_to(root_dir)
WindowsPath('test_file')
param = 'test_file/nested'
Path(root_dir).joinpath(param).relative_to(root_dir)
WindowsPath('test_file/nested')
param = 'non_existing/../../data'
Path(root_dir).joinpath(param).resolve().relative_to(root_dir.resolve())
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-26-a74379fe1817> in <module>() .... ValueError: 'C:\\python_scripts\\PyCharmProjects\\data' does not start with 'C:\\python_scripts\\PyCharmProjects\\testproject'
param = 'non_existing/../nested'
Path(root_dir).joinpath(param).resolve().relative_to(root_dir.resolve())
WindowsPath('nested')
Upvotes: 11