webfreemedium

JerryTok

hackthebox

Task: Symfony 7.0 PHP app with Twig SSTI via createTemplate(), but exec functions disabled and open_basedir=/www. Solution: Use Twig map filter to call file_put_contents, write .htaccess enabling CGI + shell script calling SUID /readflag, bypassing all PHP restrictions.

$ ls tags/ techniques/
twig_ssti_createtemplatemap_filter_callbackfile_put_contents_via_twightaccess_cgi_executiondisable_functions_bypass_via_cgiopen_basedir_bypass_via_cgi

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

JerryTok — HackTheBox

Description

Welcome to JerryTok, your portal to the nearest jerryboree, where mediocrity is celebrated! Dive into the daily escapades of the wonderfully average, from mundane mishaps to modest triumphs. Share your moments, connect, and laugh as you find glory in the ordinary. Join now and embrace the delightfully dull at your local jerryboree!

A Symfony 7.0 PHP web application using Twig 3.8.0 as the template engine, running on Apache with PHP-CGI on Alpine Linux. The goal is to read a flag at /root/flag that is only accessible via a SUID root binary /readflag.

Analysis

SSTI Vulnerability

In DefaultController.php, the location GET parameter is directly interpolated into a Twig template string via createTemplate() — a textbook Server-Side Template Injection:

$location = $request->get('location'); $message = $this->container->get('twig')->createTemplate( "Located at: {$location} from your ship's computer" )->render();

Restrictions Preventing Trivial Exploitation

  1. disable_functions (from entrypoint.sh):

    exec, system, popen, proc_open, shell_exec, passthru, ini_set, putenv, pfsockopen, fsockopen, socket_create, mail
    

    All standard command execution functions are blocked.

  2. open_basedir = /www — PHP file operations restricted to the /www directory only.

  3. Flag location: /root/flag, readable only by root. A SUID root binary /readflag (chmod 4755) must be executed to retrieve it:

    int main() { setuid(0); system("/bin/cat /root/flag"); }

Key Observations from Source Code

  1. Apache httpd.conf loads mod_cgi and has ScriptAlias /cgi-bin /usr/bin. Crucially, AllowOverride All is set for both / and /www/public, meaning .htaccess files are fully processed.

  2. The file .htacess (single 's') is a deliberate typo — Apache only reads .htaccess (double 's'), so Symfony's rewrite rules are NOT active. This means we can write our own .htaccess and it will be the authoritative one.

...