2011-08-15 7 views
6

Tengo un formulario que envía una cadena a mi aplicación Flask cuando se publica el formulario. La cadena es una ruta de archivo, por lo que me gustaría asegurarme de que no contenga nada desagradable, como ../../../etc/passwd. Werkzeug, que usa Flask, tiene una función útil llamada secure_filename que quita cosas desagradables de los nombres de archivos. Desafortunadamente, cuando se alimenta con una ruta completa como templates/example.html, convierte / en _, por lo que terminamos en templates_example.html.¿Cómo puedo pasar de forma segura una ruta de acceso arbitrariamente profunda a una aplicación web (Frasco, en este caso)?

Parece sensato dividir la ruta en niveles, así que envío templates y example.html por separado y luego los vuelvo a unir en el servidor. Esto funciona muy bien, excepto que el camino puede ser arbitrariamente profundo. Podría simplemente juntar dir1/dir2/dir3/dir4 y esperar que nadie sea más profundo que dir4, pero parece tonto.

¿Cuál es la forma correcta de manejar la validación de rutas de profundidad desconocida? Validar de manera diferente? ¿Enviar los datos de manera diferente? Codifique la ruta de manera diferente, luego decodifíquela en el servidor?

Respuesta

2

Puede utilizar werkzeug.routing.PathConverter para manejar caminos arbitrarios, así:

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

Con la muestra simplificada anterior se puede ver que si visita http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4 volverá dir1/dir2/dir3/dir4 y si usted visita http://127.0.0.1:5000/arbitrary/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10 se volverá dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10

+2

Ese es su navegador que resuelve la ruta. Por sí solo, el convertidor de ruta no desinfecta la ruta. Vea mi respuesta a continuación para encontrar la solución adecuada para ese problema. –

+0

Estoy de acuerdo con Armin. Confiar en '' para asegurar una ruta de archivo no es suficiente y es un gran agujero de seguridad. –

8

Para situaciones como esta Flask tiene safe_join que aumenta 404 si un usuario intenta abandonar la ruta:

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

Miré 'safe_join', pero no pensé que funcionaría así. Esta es la línea en 'safe_join' haciendo el filtrado de' ../ ', ¿verdad? https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/security.py#L139 ¿Cómo saca el '../' del medio de la cadena? – pingswept

Cuestiones relacionadas