应使用send_from_directory替代send_file并配合路径校验与流式传输:先过滤非法字符,再用realpath+commonpath确保路径在白名单目录内,大文件需response流式返回避免内存溢出。

send_file 传本地文件时路径穿越漏洞怎么防
直接用 send_file 返回用户指定路径的文件,等于把服务器文件系统裸露给请求参数——filename=../../etc/passwd 就能读到敏感配置。这不是“可能出问题”,而是只要没做校验,必然被利用。
- 永远不要拼接用户输入进文件路径:
os.path.join(UPLOAD_FOLDER, request.args.get('file'))是高危写法 - 必须用
os.path.realpath+os.path.commonpath做路径规范化和白名单校验 - 推荐只允许从预设目录(如
DOWNLOADS_DIR)下发,且强制限定后缀(如仅.pdf,.csv)
# 安全示例:校验路径是否落在 DOWNLOADS_DIR 下
filename = request.args.get('file', '')
safe_path = os.path.realpath(os.path.join(DOWNLOADS_DIR, filename))
if os.path.commonpath([safe_path, DOWNLOADS_DIR]) != DOWNLOADS_DIR:
abort(404)
return send_file(safe_path)
send_from_directory 为什么比 send_file 更适合静态资源下载
send_from_directory 内置了路径安全检查,它不信任任何传入路径,只接受一个「根目录」+ 一个「相对子路径」,自动拒绝向上跳转。而 send_file 是完全自由的文件句柄操作,责任全在开发者。
-
send_from_directory的directory参数必须是绝对路径,filename必须是相对路径(不能含..或/开头) - 它会自动调用
os.path.join(directory, filename)并做os.path.isabs和规范化判断,失败直接 404 - 但注意:如果
filename来自用户输入,仍需先过滤掉非法字符(如
