Как безопасно передать произвольно глубокий путь к веб-приложению (в данном случае Flask)? - PullRequest
6 голосов
/ 15 августа 2011

У меня есть форма, которая отправляет строку в мое приложение Flask при публикации формы. Строка - это путь к файлу, поэтому я хочу убедиться, что она не содержит ничего противного, например ../../../etc/passwd. Werkzeug, который использует Flask, имеет удобную функцию под названием secure_filename, которая удаляет неприятные вещи из имен файлов. К сожалению, при заполнении полного пути, например templates/example.html, он преобразует / в _, поэтому мы получаем templates_example.html.

Поэтому представляется разумным разделить путь на уровни, поэтому я отправляю templates и example.html по отдельности, а затем снова соединяю их вместе на сервере. Это прекрасно работает, за исключением того, что путь может быть сколь угодно глубоким. Я мог бы просто связать вместе dir1/dir2/dir3/dir4 и надеяться, что никто не пойдет глубже, чем dir4, но это кажется глупым.

Как правильно обрабатывать проверку путей неизвестной глубины? Подтвердить по-другому? Отправить данные по-другому? Кодировать путь по-другому, а затем декодировать его на сервере?

Ответы [ 2 ]

9 голосов
/ 17 августа 2011

Для таких ситуаций, как эта колба имеет safe_join, что повышает 404, если пользователь пытается покинуть путь:

>>> safe_join('/foo/bar', 'test')
'/foo/bar/test'
>>> safe_join('/foo/bar', 'test/../other_test')
'/foo/bar/other_test'
>>> safe_join('/foo/bar', 'test/../../../etc/htpassw')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mitsuhiko/Development/flask/flask/helpers.py", line 432, in safe_join
    raise NotFound()
werkzeug.exceptions.NotFound: 404: Not Found
2 голосов
/ 16 августа 2011

Вы можете использовать werkzeug.routing.PathConverter для обработки произвольных путей, например, так:

from flask import Flask
app = Flask(__name__)

@app.route("/arbitrary/<path:my_path>")
def arbitrary_path(my_path):
    return my_path

if __name__ == "__main__":
    app.run()

С приведенным выше упрощенным примером вы можете увидеть, что если вы посетите http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4, это будетвернуть dir1/dir2/dir3/dir4 и если вы посетите http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10, он вернется dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10

...