SSTI 就是服务器端模板注入(Server-Side Template Injection)
flask是用python编写的一个轻量web开发框架。
漏洞成因
漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。’
jinja2
Jinja2是一种面向Python的现代和设计友好的模板语言 Jinja2使用 {{name}}结构表示一个变量,它是一种特殊的占位符,告诉模版引擎这个位置的值从渲染模版时使用的数据中获取。
|
漏洞原因:
flask使用jinjia2渲染引擎进行网页渲染,当处理不得当,未进行语句过滤,用户输入,会导致渲染出恶意代码,形成注入。
主要是用了render_template_string
这个函数,直接渲染执行了字符串
代码实现
代码实现简单的渲染,利用render_template
函数渲染
app.py
from flask import Flask from flask import render_template,request
app = Flask(__name__)
@app.route('/') @app.route('/index') def index(): bai = request.args.get('bai') return render_template('index.html',name=bai)
if __name__ == '__main__': app.debug = True app.run()
|
index.html
<html> <head> <title>小猪佩奇</title> </head> <body> <h1>Hello, {{name}}!</h1> </body> </html>
|
运行起来后,访问127.0.0.1:5000
通过输入参数可以进行简单的渲染,代码不能执行
`{{name}}`是被{{}}包起来的,会预先渲染转义,然后才输出,不会被渲染执行
|
利用render_template_string
函数
app.py
from flask import Flask from flask import render_template,request,render_template_string
app = Flask(__name__)
@app.route('/') @app.route('/index') def index(): bai = request.args.get('bai') str = ''' <html> <head> <title>小猪佩奇</title> </head> <body> <h1>Hello, {}!</h1> </body> </html> '''.format(bai) return render_template_string(str)
if __name__ == '__main__': app.debug = True app.run()
|
代码被成功执行,return render_template_string(str)会将{}里的字符串当成代码指令
flask相关知识
由于在jinja2中是可以直接访问python的一些对象及其方法的,所以可以通过构造继承链来执行一些操作,比如文件读取,命令执行等
魔术方法
__class__ :返回一个实例所属的类 __mro__ :返回当前类对象的所有继承类 __bases__ :以元组形式返回一个类直接所继承的类(可以理解为直接父类)__base__ :和上面的bases大概相同,都是返回当前类所继承的类,即基类,区别是base返回单个,bases返回是元组 // __base__和__mro__都是用来寻找基类的 __subclasses__ :以列表返回类的子类 __init__ :类的初始化方法 __globals__ :对包含函数全局变量的字典的引用
|
class A:pass class B(A):pass class C(B):pass class D(B):pass c = D() print(c.__class__.__base__) print(c.__class__.__mro__) print(c.__class__.__mro__[2]) print(c.__class__.__mro__[2].__subclasses__()) print(c.__class__.__base__.__subclasses__()) print(c.__class__.__base__.__subclasses__()[1])
|
<class '__main__.B'> (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) <class '__main__.A'> [<class '__main__.B'>] [<class '__main__.C'>, <class '__main__.D'>] <class '__main__.D'>
|
绕过姿势
绕过姿势
以后再写吧,看大佬的吧