from flask import Flask, request, render_template, send_file app = Flask(__name__)
@app.get("/<path:file_path>") def download_file(file_path: str): if '../' in file_path: file_path = file_path.replace('../', '') return send_file(file_path) if __name__ == '__main__': app.run()
看似安全的防护措施实际上有一个很简单的绕过方法:双写绕过 —— 使用….//代替../
这样../被替换一次后还剩一个../依然可以完成路径穿越
windows下禁止/..
同样看起来相当安全的过滤
1 2 3 4 5 6 7 8 9 10
from flask import Flask, request, render_template, send_file app = Flask(__name__)
@app.get("/<path:file_path>") def download_file(file_path: str): if '/..' in file_path: return 'Invalid path' return send_file(file_path) if __name__ == '__main__': app.run()
各位可以看一下有什么思路
答案其实很简单,我们可以祭出windows下路径穿越的神器:%5C(正反斜杠)
windows下/%5C..在路径解析的时候会将\忽略,这个漏洞在open函数中也奏效,即:
1 2 3 4 5 6 7 8 9 10 11
from flask import Flask, request, render_template, send_file app = Flask(__name__)
@app.get("/<path:file_path>") def download_file(file_path: str): if '/..' in file_path: return 'Invalid path' with open(file_path, 'r') as f: return f.read() if __name__ == '__main__': app.run()
windows下禁止../
1 2 3 4 5 6 7 8 9 10 11
from flask import Flask, request, render_template, send_file app = Flask(__name__)
@app.get("/<path:file_path>") def download_file(file_path: str): if '../' in file_path: return 'Invalid path' with open(file_path, 'r') as f: return f.read() if __name__ == '__main__': app.run()
与上一个一样,使用正反斜杠绕过
禁止../../和\
省流:正反斜杠G了
1 2 3 4 5 6 7 8 9 10 11
from flask import Flask, request, render_template, send_file app = Flask(__name__)
@app.get("/<path:file_path>") def download_file(file_path: str): if '../../' in file_path or '\\' in file_path: return 'Invalid path' with open(file_path, 'r') as f: return f.read() if __name__ == '__main__': app.run()