writeup.md

Giftzwerg02

Last modified: 2024-08-15, 15:20:19

LoveTok

One of the Challenges of HTB called “LoveTok” (Category: Web). We were given an IP+Port to a Host and also a full “fake-deployment” of it in a zip-file.

Since this is a Web-Challenge I just assumed that a website would be running on that port, I was right:

First looks

The only form of interaction we currently have is this button on the bottom, let’s click it:

After click

The page itself didn’t change but we can see that we now have a GET-Param in the URL. After fiddelingwith it a little bit and also from the name itself I quickly figured that you can define a Date-Format String for the Output below. After some professional googlin’ I also figured out that the backend is most-likely a PHP-Server given how it behaves on certain format-strings (note: this could’ve been figured out in 0 seconds by just simply having a look at the provided zip-file first :().

Anyhow, since this is now our only form of input it virtually screams “Please hack here” - let’s have a look at the provided files:

Provided Stuff

Two of the files are related to our time-formatting: TimeController.php and TimeModel.php. I have added the entierty of them below and annotated them using comments:

If we wouldn’t have the addslashes we could very easily just inject anything by simply closing the date-call ourselves, appending any call we want and just commenting out the rest. But since this isn’t possible (since directly providing " gets escaped to \") we have to get a bit more creative.

Doing a quick google-search immediately provides multiple articles as to why addslashes does not properly sanatize input and how it can be exploited anyway! The article I used here.

To summarize: Although some characters get escaped, we can still run PHP-String interpolation and with that have access to any variable and function that is currently in scope. The crafts a concise command that allows us to do any command-injection that we want!

  1. Add a second URL-GET-Param that contains our command-injection payload. e.g.: http://...&1=<anything>. Note: I thought that the article used a number as the key so that we do not have to quote it to access the value, which would’ve been a problem since we cannot quote anything. But we can “exploit” PHP’s String-Interpolation to bypass the need of quotes (which is very cursed!)
<?php
$c = array("foo" => 3);
var_dump($c[foo]); // does not work, as expected
var_dump("{$c[foo]}"); // does not work, as expected
var_dump("$c[foo]"); // WORKS, only $c[] is interpolated and the rests (anything passed inside of []) is interpreted as a string! WTF!
?>
  1. Reference the GET-Param in the original variable (which gets passed to the eval-function) and wrap it in a system-call to run arbitrary code: system($_GET[1])

With that we can simply take the example from the article, although I do know from the provided files that there is a flag-file on the server which looks like /flag* (with some random characters at the end), so we don’t even have to run ls to find it, but let’s have a look anyway:

  1. List files: ?format=${system($_GET[1])}&1=ls%20/ Flag spotted
  2. Read file content: ?format=${system($_GET[1])}&1=cat%20/flag* Flag gotted

And there we go!