Ваш код не предотвращает обратный путь в каталогах. Вы можете защититься от этого с помощью модуля os.path .
>>> import os.path
>>> os.curdir
'.'
>>> startdir = os.path.abspath(os.curdir)
>>> startdir
'/home/jterrace'
startdir
теперь является абсолютным путем, где вы не хотите, чтобы этот путь выходил за пределы. Теперь предположим, что мы получаем имя пользователя от пользователя, а нам дается злонамеренный /etc/passwd
.
>>> filename = "/etc/passwd"
>>> requested_path = os.path.relpath(filename, startdir)
>>> requested_path
'../../etc/passwd'
>>> requested_path = os.path.abspath(requested_path)
>>> requested_path
'/etc/passwd'
Мы теперь преобразовали их путь в абсолютный путь относительно нашего начального пути. Поскольку этого не было в начальном пути, у него нет префикса нашего начального пути.
>>> os.path.commonprefix([requested_path, startdir])
'/'
Вы можете проверить это в своем коде. Если функция commonprefix возвращает путь, который не начинается с startdir
, то этот путь недопустим, и вы не должны возвращать содержимое.
Вышеприведенное может быть преобразовано в статический метод следующим образом:
import os
def is_directory_traversal(file_name):
current_directory = os.path.abspath(os.curdir)
requested_path = os.path.relpath(file_name, start=current_directory)
requested_path = os.path.abspath(requested_path)
common_prefix = os.path.commonprefix([requested_path, current_directory])
return common_prefix != current_directory