Flask send_file函数导致的绝对路径遍历
2022-7-18 17:30:14 Author: mp.weixin.qq.com(查看原文) 阅读量:15 收藏

平时接触到的 python 项目并不多,对 python 的代码审计更是没有接触,偶然朋友发来了一个漏洞 Flask send_file函数导致的绝对路径遍历 ,感觉打开了新世界的大门,于是就以一个初学者的角度,进行复现分析一下。详情也可以根据 Python : Flask Path Traversal Vulnerability 进行分析学习

send_file 的妙用
 在以 flask 框架开发的系统中,为了直接实现用户访问某一个 URL 时就可以下载到文件,我们就使用 send_file 来实现
from flask import Flaskfrom flask import send_file
app = Flask(__name__)

@app.route('/download')def downloadFile(): path = "test.txt" return send_file(path)

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

 

我们看到 如此运行的效果是直接返回了文件的内容,浏览器并没有识别成一个文件下载下来。
要想让浏览器识别成为文件下载的话,只需要加上as_attachment=True
from flask import Flaskfrom flask import send_file
app = Flask(__name__)

@app.route('/download')def downloadFile(): path ="test.txt" return send_file(path, as_attachment=True)

if__name__=='__main__':    app.run()

 

 当下载的文件名是中文时

from flask import Flaskfrom flask import send_file
app = Flask(__name__)

@app.route('/download')def downloadFile(): path ="测试.txt" return send_file(path, as_attachment=True)

if__name__=='__main__': app.run()

 

Content-Disposition:
 Content-Disposition
 在常规的 HTTP 应答中,Content-Disposition 响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。其可以是inline(默认值,所以可以不指定)或者是attachment,attachment表示附件,浏览器看到这个值一般会弹出一个保持文件的确认框,或者像chrome直接下载。

 

 

漏洞分析
 漏洞的触发是在 send_file 中,我们跟进看一下
 flask.helpers.send_file

 

 继续跟进查看
 werkzeug.utils.send_file

 

 我们在本地构造一个简单的语句进行尝试

>>>import os.path>>> _root_path ="path/to/mySafeStaticDir">>> path_or_file ="/../../../../../../../etc/passwd">>> os.path.join(_root_path,path_or_file)'/../../../../../../../etc/passwd'

 

 我们发现 os.path.join 使用不受信任的输入调用时不安全的。当 os.path.join 调用遇到绝对路径时,它会忽略在该点之前遇到的所有参数并开始使用新的绝对路径。当参数可控时,我们控制恶意参数输入绝对路径,os.path.join 会完全忽略静态目录。所以,当 os.path.join 来获取来自 flask.send_file 的不受信任的输入时,可能会目录遍历攻击。
漏洞复现
 我们在本地构造简单的代码进行测试,获取从外部传入的参数 filename
from flask import Flask, requestfrom flask import send_file
app = Flask(__name__)

@app.route('/download')def downloadFile(): filename = request.args.get('filename') return send_file(filename, as_attachment=True)
if__name__=='__main__': app.run()

 通过控制 filename 为绝对路径,就实现了目录穿越漏洞

 

 

 

总结反思
这个漏洞非常的有趣,漏洞的修复是可以使用flask.safe_join加入不受信任的路径或用flask.send_file调用替换flask.send_from_directory调用。
这个漏洞虽然很简单,但是在 github 上很多用 python 开发的项目都用了这个函数,如果不加以修复,会造成很大的危害。
原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:[email protected]

文章类型:黑客极客技术、信息安全热点安全研究分析安全相关

通过审核并发布能收获200-800元不等的稿酬。

更多详情,点我查看!

靶场实操,戳“阅读原文“

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&mid=2652889114&idx=1&sn=5148e94127c2bca1bf5093f7a8c079fd&chksm=bd599cd78a2e15c11b645c7396d0976e87fb647106e48e50af6f5a55f2b509c002c89c368201#rd
如有侵权请联系:admin#unsafe.sh