4

我需要防止directory traversal attack我的代码使用 Python。我的代码如下:

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")

在这里我需要用户像http://127.0.0.1:8000/createfile/?param=../../../../../../../../etc/passwd这样运行它应该防止目录遍历攻击。

4

2 回答 2

9

假设用户内容都位于

safe_dir = '/home/saya/server/content/'

正如heinrichj提到的,结尾/很重要,以确保下面的检查与特定目录匹配。

您需要验证最终请求是否存在:

if os.path.commonprefix((os.path.realpath(requested_path),safe_dir)) != safe_dir: 
    #Bad user!

如果允许请求的路径是save_dir自身,则还需要允许进入 if os.path.realpath(requested_path)+'/' == safe_dir

我鼓励您确保所有您希望用户可以在一个地方访问的内容。

于 2017-07-19T11:13:53.940 回答
3

您可以尝试以下方法pathlib.Path

Path(root_dir).joinpath(param).resolve().relative_to(root_dir.resolve())

应该返回从 开始的相对路径,或者如果尝试目录遍历攻击,则root_dir引发ValueError

测试

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('嵌套')

于 2017-07-19T12:09:27.553 回答