Inspect Java Web project source code, identify XML parsing implementations, and detect XXE (XML External Entity) injection vulnerabilities.
Core Requirements
This skill must fully inspect all XML parsing-related code; omissions are not allowed.
- ✅ Identify all XML parsing entry points (5 types of parsers)
- ✅ Check the external entity protection configuration of each parser
- ✅ Trace XML input sources (user controllability)
- ✅ Detect echo points (whether data is returned to the user)
- ✅ Provide a verification PoC for each vulnerability point
- ❌ Omitting any XML parsing operation is prohibited
- ❌ Skipping decompilation steps is prohibited
Vulnerability Severity Classification Standards
- Vulnerability ID format:
{C/H/M/L}-XXE-{序号} - Severity level = f(reachability R, impact scope I, exploitation complexity C)
- Score = R × 0.40 + I × 0.35 + C × 0.25, mapped to CVSS 3.1
| Prefix | CVSS 3.1 | Meaning |
|---|---|---|
| 🔴 C | 9.0-10.0 | Can directly lead to system compromise |
| 🟠 H | 7.0-8.9 | Can cause major damage |
| 🟡 M | 4.0-6.9 | Can cause certain damage |
| 🔵 L | 0.1-3.9 | Security hardening item |
Skill Collaboration Workflow (CRITICAL)
java-xxe-audit must be executed after java-route-mapper, conducting the audit based on the already organized route information.
┌─────────────────────────────────────────────────────────────────┐
│ 完整审计流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [步骤1] java-route-mapper │
│ │ │
│ │ 输出: │
│ │ ├─ 所有 HTTP 路由列表 │
│ │ ├─ 每个路由的参数定义 │
│ │ └─ Content-Type 识别(application/xml, text/xml) │
│ │ │
│ ↓ │
│ [步骤2] java-xxe-audit(本技能) │
│ │ │
│ │ 输入:java-route-mapper 的输出 │
│ │ │
│ │ 执行: │
│ │ ├─ 快速扫描 XML 解析类 │
│ │ ├─ 检查解析器安全配置 │
│ │ ├─ 追踪 XML 输入来源 │
│ │ └─ 检查回显路径 │
│ │ │
│ ├─── 需要深入追踪 ───→ java-route-tracer │
│ │ │ │
│ │ ←── 返回调用链信息 ────┘ │
│ │ │
│ ↓ │
│ [步骤3] 输出综合审计报告 │
│ │
└─────────────────────────────────────────────────────────────────┘
Input Dependencies (from java-route-mapper)
Before starting the audit, you must first check whether the output file of java-route-mapper already exists:
{project_name}_audit/
├── route_mapper/
│ ├── {project_name}_route_mapper_{timestamp}.md ← 主索引(先读此文件定位模块详情)
│ ├── {module_name}/
│ │ └── {project_name}_module_{module_name}_{timestamp}.md ← 模块详情
│ └── webservice/
│ └── {project_name}_ws_{service_name}_{timestamp}.md
└── xxe_audit/
└── {project_name}_xxe_audit_{timestamp}.md ← 本技能输出
If the route_mapper output does not exist, you must first run:
Skill(skill="java-route-mapper", args="--project {project_path}")
Key Information Obtained from route_mapper
| Information | Purpose |
|---|---|
| Route path | Locate Controller/Servlet entry points |
| Content-Type | Identify endpoints that accept XML input |
| Parameter source | Identify raw input such as getInputStream() |
| Request method | POST methods are more likely to accept an XML Body |
Workflow (Three Phases)
Phase 1: Quick Scan (Execute First)
Goal: Quickly locate all XML parsing points and high-risk files.
# 1.1 搜索 XML 解析器创建
grep -ri "XMLReaderFactory.createXMLReader" --include="*.java"
grep -ri "new SAXBuilder" --include="*.java"
grep -ri "new SAXReader" --include="*.java"
grep -ri "SAXParserFactory.newInstance" --include="*.java"
grep -ri "DocumentBuilderFactory.newInstance" --include="*.java"
# 1.2 搜索 XML 解析执行点
grep -ri "\.parse\s*(" --include="*.java"
grep -ri "\.build\s*(" --include="*.java"
grep -ri "\.read\s*(" --include="*.java"
# 1.3 搜索 XML 输入来源
grep -ri "getInputStream" --include="*.java"
grep -ri "InputSource" --include="*.java"
grep -ri "StringReader" --include="*.java"
grep -ri "StreamSource" --include="*.java"
# 1.4 搜索安全配置(判断是否已防护)
grep -ri "disallow-doctype-decl" --include="*.java"
grep -ri "external-general-entities" --include="*.java"
grep -ri "external-parameter-entities" --include="*.java"
grep -ri "setFeature" --include="*.java"
grep -ri "setExpandEntityReferences" --include="*.java"
# 1.5 搜索其他 XML 相关类
grep -ri "TransformerFactory" --include="*.java"
grep -ri "SchemaFactory" --include="*.java"
grep -ri "XMLInputFactory" --include="*.java"
grep -ri "Unmarshaller\|JAXBContext" --include="*.java"
Output: List of high-risk files (sorted by priority)
| Priority | File Type | Audit Focus |
|---|---|---|
| P0 | Directly use getInputStream() + XML parsing |
Direct parsing of user-controllable XML |
| P1 | XML processing in Servlet/Controller | XML parsing at the HTTP entry point |
| P2 | XML utility class *XmlUtil*.java |
General XML parsing methods |
| P3 | WebService/SOAP processing class | SOAP XML parsing |
Phase 2: Parser Security Configuration Check
For each XML parsing point found in Phase 1, check the security configuration status one by one.
2.1 Parser Identification and Configuration Check
For each parser instance, check whether the following protection features are set:
| Protection Features | Feature URI | Effect |
|---|---|---|
| Disallow DOCTYPE | http://apache.org/xml/features/disallow-doctype-decl |
Strictest, recommended |
| Disallow external general entities | http://xml.org/sax/features/external-general-entities |
Disable external entity references |
| Disallow external parameter entities | http://xml.org/sax/features/external-parameter-entities |
Disable parameter entities |
| Disallow external DTD loading | http://apache.org/xml/features/nonvalidating/load-external-dtd |
Disallow loading external DTDs |
For detailed detection rules, see the reference documentation for each parser:
| Parser | Reference |
|---|---|
| XMLReader | PARSERS.md - XMLReader section |
| SAXBuilder (JDOM2) | PARSERS.md - SAXBuilder section |
| SAXReader (dom4j) | PARSERS.md - SAXReader section |
| SAXParserFactory | PARSERS.md - SAXParserFactory section |
| DocumentBuilderFactory | PARSERS.md - DocumentBuilderFactory section |
2.2 XML Input Source Tracing
For each XML parsing point, trace the input source:
HTTP 请求体: request.getInputStream()
↓
InputSource / StringReader / StreamSource
↓
XMLReader.parse() / SAXBuilder.build() / SAXReader.read() / ...
↓
解析结果: Document / Element / Node
↓
回显: response.getWriter().write() / model.addAttribute() / ...
| Input Source | User Controllability | Risk Level |
|---|---|---|
request.getInputStream() |
Fully controllable | High risk |
request.getParameter("xml") |
Fully controllable | High risk |
@RequestBody String xml |
Fully controllable | High risk |
MultipartFile.getInputStream() |
Fully controllable | High risk |
| XML fields read from the database | Indirectly controllable | Medium risk |
| Configuration files/hardcoded XML | Not controllable | Low |
2.3 Echo Path Check
The XXE exploitation method depends on whether there is echo:
| Echo Method | Exploitation Type | Detection Method |
|---|---|---|
| Parsing result written to HTTP response | XXE with echo | Search response.getWriter(), getText(), getTextContent() |
| Parsing result written to page model | XXE with echo | Search model.addAttribute(), request.setAttribute() |
| Parsing result only used for logic processing | Blind XXE (OOB) | Requires exfiltrating data via external DTD |
| Parsed but no output at all | Blind XXE (OOB) | Requires exfiltrating data via external DTD |
Stage 3: Detailed Detection and Reporting
3.1 Trigger java-route-tracer
When the following situations are found, call java-route-tracer to obtain the complete call chain:
| Trigger Condition | Invocation Method |
|---|---|
| XML input passes through multiple layers | Skill(skill="java-route-tracer", args="--route {route}") |
| Parser is in a utility class/base class | Skill(skill="java-route-tracer", args="--route {route}") |
| Echo path is unclear | Skill(skill="java-route-tracer", args="--route {route}") |
3.2 Generate Report
Integrate all detection results and generate a comprehensive audit report.
XML Parser Identification
| Parser | Identification Feature | Package/Dependency | Reference |
|---|---|---|---|
| XMLReader | XMLReaderFactory.createXMLReader(), xmlReader.parse() |
org.xml.sax (JDK built-in) |
PARSERS.md |
| SAXBuilder | new SAXBuilder(), saxBuilder.build() |
org.jdom2 (jdom2) |
PARSERS.md |
| SAXReader | new SAXReader(), reader.read() |
org.dom4j.io (dom4j) |
PARSERS.md |
| SAXParserFactory | SAXParserFactory.newInstance(), .getXMLReader().parse() |
javax.xml.parsers (JDK built-in) |
PARSERS.md |
| DocumentBuilderFactory | DocumentBuilderFactory.newInstance(), builder.parse() |
javax.xml.parsers (JDK built-in) |
PARSERS.md |
Other components potentially affected by XXE
| Component | Identification Feature | Vulnerability Description |
|---|---|---|
| TransformerFactory | TransformerFactory.newInstance() |
XSLT processing can trigger XXE |
| SchemaFactory | SchemaFactory.newInstance() |
XML Schema validation can trigger XXE |
| XMLInputFactory (StAX) | XMLInputFactory.newInstance() |
StAX parser can trigger XXE |
| JAXB Unmarshaller | JAXBContext.newInstance(), unmarshaller.unmarshal() |
XML deserialization can trigger XXE |
Decompilation Stage (CRITICAL)
When source code is unavailable, CFR decompiler must be used to decompile XML parsing-related classes.
For detailed strategy, see DECOMPILE_STRATEGY.md
Decompiler tool invocation
# 反编译单个 XML 处理类
java -jar {CFR_JAR} /path/to/XmlParser.class --outputdir {output_path}/decompiled
# 反编译 XML 处理相关目录
find /path/to/WEB-INF/classes/com/example/util -name "*.class" | xargs java -jar {CFR_JAR} --outputdir {output_path}/decompiled
# 反编译多个指定文件
java -jar {CFR_JAR} /path/to/XmlUtil.class /path/to/XmlParser.class /path/to/SoapHandler.class --outputdir {output_path}/decompiled
Classes that must be decompiled
| Type | Match pattern | Purpose |
|---|---|---|
| XML utility class | *Xml*.class, *XML*.class, *Parser*.class |
Extract XML parsing logic |
| Servlet | *Servlet.class, *Controller.class |
Trace input source |
| WebService | *WebService*.class, *Soap*.class, *WS*.class |
SOAP XML processing |
| Filter | *Filter.class |
XML request preprocessing |
XXE detection rules quick reference
⚠️ Dangerous patterns (parsers without secure configuration)
| Parser | Dangerous code | Vulnerability description |
|---|---|---|
| XMLReader | XMLReaderFactory.createXMLReader() directly after parse() |
External entities not disabled |
| SAXBuilder | new SAXBuilder() directly after build() |
External entities not disabled |
| SAXReader | new SAXReader() directly after read() |
External entities not disabled |
| SAXParserFactory | SAXParserFactory.newInstance() directly after parse() |
External entities not disabled |
| DocumentBuilderFactory | DocumentBuilderFactory.newInstance() directly after parse() |
External entities not disabled |
✅ Safe patterns (protection configured)
The secure fix is the same for all parsers—disable DOCTYPE or external entities:
// 方式1: 禁止 DOCTYPE 声明(最严格,推荐)
setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 方式2: 分别禁用外部实体
setFeature("http://xml.org/sax/features/external-general-entities", false);
setFeature("http://xml.org/sax/features/external-parameter-entities", false);
setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
⚠️ Input source detection (CRITICAL - confirm user controllability)
Input source patterns that must be searched:
# HTTP 请求体
grep -ri "getInputStream" --include="*.java"
grep -ri "getReader" --include="*.java"
# 参数传入 XML
grep -ri "getParameter.*xml\|getParameter.*XML" --include="*.java"
# Spring 注解
grep -ri "@RequestBody" --include="*.java"
# 文件上传
grep -ri "MultipartFile" --include="*.java" | grep -i "xml"
# SOAP/WebService
grep -ri "@WebService\|@WebMethod" --include="*.java"
Data flow tracing (load java-route-tracer when needed)
When parameter tracing is needed
| Scenario | Description | Action |
|---|---|---|
| XML input passes through multiple layers | HTTP request body passes through Controller → Service → Util multiple layers before parsing | Load java-route-tracer |
| Parser is in a utility class | XML parsing is in a general XmlUtil class, called from multiple places | Load java-route-tracer |
| Echo path is unclear | Parsing result is output after multiple conversions | Load java-route-tracer |
| SOAP processing chain | WebService request passes through interceptor/handler chain | Load java-route-tracer |
Automatically trigger java-route-tracer
# 当需要追踪 XML 输入流向时
Skill(
skill="java-route-tracer",
args="--route {controller_route} --project {project_path}"
)
Report generation
Output a single comprehensive audit report file:
{project_name}_audit/xxe_audit/
└── {route_name}/
└── {project_name}_xxe_audit_{timestamp}.md # 综合审计报告
Route name description:
- The route name is extracted from the route path, removing the leading slash and special characters
- For example:
/api/xml/parse→api_xml_parse - For example:
/ws/soap/endpoint→ws_soap_endpoint
Output format
Strictly follow references/OUTPUT_TEMPLATE.md to generate the output file using the fill-in template.
- File name format:
{project_name}_xxe_audit_{YYYYMMDD_HHMMSS}.md - Do not modify the template structure, do not add or remove sections, do not adjust the order
- All [fill in] placeholders must be replaced with actual content
- General specification reference: java-shared/OUTPUT_STANDARD.md
- Vulnerability aggregation rules reference: java-shared/VULNERABILITY_GROUPING.md, multiple entry points with the same root cause are merged into one vulnerability ID and the "affected entry points" are listed; entry points with different conditions are split.
Verification checklist
Before marking the audit complete, the following checks must be performed:
Code detection checks
- All XML parsing classes have been checked
- All 5 parser types have been searched
- Security configuration checked for each parser instance
Input Source Check
- Traced the XML input source for each parser
- Confirmed whether the input is user-controllable
- Checked the echo path
Vulnerability Detection Check
- All unprotected parsers have been flagged
- All user-controllable inputs have been traced
- Distinguished between echoed XXE and Blind XXE
Report Completeness Check
- The comprehensive audit report has been generated and passed the self-check checklist at the end of OUTPUT_TEMPLATE.md
References
- OUTPUT_TEMPLATE.md - Output report fill-in template
- PARSERS.md - Detailed detection rules for five XML parsers
- DECOMPILE_STRATEGY.md - Decompilation strategy guide