开发者

How can I securely pass an arbitrarily deep path to a webapp (Flask, in this case)?

I have a form that sends a string to my Flask app when the form is posted. The string is a filepath, so I'd like to make sure i开发者_JS百科t doesn't contain anything nasty, like ../../../etc/passwd. Werkzeug, which Flask uses, has a handy function called secure_filename that strips nasty stuff out of filenames. Unfortunately, when fed a full path like templates/example.html, it converts the / to _, so we end up with templates_example.html.

It seems sensible, then, to split the path up into levels, so I send templates and example.html separately and then join them together again on the server. This works great, except that the path can be arbitrarily deep. I could just string together dir1/dir2/dir3/dir4 and hope that nobody every goes deeper than dir4, but that seems dumb.

What's the right way to handle validation of paths of unknown depth? Validate differently? Send the data differently? Encode the path differently, then decode it on the server?


For situations like this Flask has safe_join which raises 404 if a user attempts to leave the path:

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


You can use werkzeug.routing.PathConverter to handle arbitrary paths like so:

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

With the oversimplified sample above you can see that if you visit http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4 it will return dir1/dir2/dir3/dir4 and if you visit http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10 it will return dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜