SSTI 模板注入介绍
SSTI(Server-Side Template Injection)模板注入是一种特殊的代码注入攻击,在使用模板引擎的 Web 应用程序中广泛存在。攻击者通过输入恶意数据,触发模板引擎解析执行攻击代码,从而控制应用程序并获取敏感信息。
以下是一个基于 Jinja2 模板引擎的 SSTI 模板注入攻击案例:
-
首先,攻击者访问目标网站并找到一个可以利用的输入点,如搜索框或评论框等。
-
攻击者在输入框中输入以下 Jinja2 代码:
{{config.items()}}
该代码将显示应用程序的配置项。
- 当应用程序解析该输入时,恶意代码将被执行,显示应用程序的配置项,如下所示:
[('SECRET_KEY', '123456789'), ('SQLALCHEMY_DATABASE_URI', 'mysql://root:password@localhost/test'), ('DEBUG', 'True')]
通过 SSTI 模板注入攻击,攻击者可以轻松地获取应用程序的敏感信息并最终控制服务器。因此,开发人员应该采取必要的安全措施,防止 SSTI 模板注入攻击。
SSTI 模板注入利用
Jinja2 模板中可以访问一些 Python 内置变量,如 [] {} 等,并且能够使用 Python 变量类型中的一些函数,这里其实就引出了 Python 沙盒逃逸。
Python 的内置函数非常强大,可以调用一切函数做自己想做的事情。
在 Python 的 object 类中集成了很多的基础函数,我们想要调用的时候也是需要用 object 去操作的,这是两种创建 object 的方法。
Python 中一些常见的特殊方法:
__class__返回调用的参数类型。__base__返回基类__mro__允许我们在当前 Python 环境下追溯继承树__subclasses__()返回子类
现在我们的思路就是从一个内置变量调用 __class__.__bases__ 等隐藏属性,去找到一个函数,然后调用其 __globals__['builtins'] 即可调用 eval 等执行任意代码。
builtins 即是引用,Python 程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于 builtins 却不用导入,它在任何模块都直接可见,所以这里直接调用引用的模块。
().__class__.__bases__[0]
''.__class__.__mro__[2]
{}.__class__.__bases__[0]
[].__class__.__bases__[0]
>>> ''.__class__.__base__.__subclasses__() # 返回子类的列表
[...]
# 从中随便选一个类,查看它的__init__
>>> ''.__class__.__base__.__subclasses__()[].__init__ <slot wrapper of objects>
.__class__.__base__.__subclasses__()[].__init__
.__class__.__base__.__subclasses__()[].__init__.__globals__[][]


