2011-08-15 3 views
6

私はフォームが投稿されたときにFlaskアプリケーションに文字列を送信するフォームを持っています。文字列はファイルパスなので、../../../etc/passwdのような厄介なものは含まれていないことを確認したいと思います。 Flaskが使用するWerkzeugには、secure_filenameと呼ばれる便利な機能があり、ファイル名から厄介なものを取り除きます。残念ながら、templates/example.htmlのようなフルパスを入力すると、/_に変換されるので、最終的にはtemplates_example.htmlになります。Webアプリケーション(Flask、この場合)に任意の深いパスを安全に渡す方法はありますか?

パスをレベルに分割することは賢明だと思うので、templatesexample.htmlを別々に送信してから、再びサーバーに参加させてください。これは、パスが任意に深いことができることを除いて、素晴らしいです。私はちょうど一緒にdir1/dir2/dir3/dir4を紐で結ぶことができ、誰もがdir4より深くなることを願っていませんが、それはダムのようです。

深さが不明なパスの検証を処理する正しい方法は何ですか?異なる検証をしますか?データを別に送信しますか?パスを別々に符号化し、サーバー上でデコードしますか?

あなたがそうのような任意のパスを処理するために werkzeug.routing.PathConverterを使用することができます

答えて

2

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

を返すことを見ることができ、上記
+2

あなたのブラウザはパスを解決しています。それ自体では、パスコンバータはパスをサニタイズしません。その問題の適切な解決方法については、私の答えを参照してください。 –

+0

私はArminに同意します。ファイルパスを確保するために ''に依存するだけでは不十分で、大きなセキュリティホールです。 –

8

このような状況の場合、Flaskには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 
+1

私は 'safe_join'を見ましたが、私はこのように動作するとは思わなかった。これは、 '../'のフィルタリングを行う 'safe_join'の行です。 https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/security.py#L139文字列の中央から '../'を引き出す方法は? – pingswept

関連する問題