SSTI模版注入
SSTI模版注入
模板引擎
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,利用模板引擎来生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成模板+用户数据的前端html页面反馈给浏览器,呈现在用户面前。
模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过
漏洞成因
服务端在接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性
常见模版引擎
漏洞攻击
模板注入通过传输型如{{xxx}}的执行命令来进行,同时针对不同的模版引擎有不同的针对注入方法
如在tornado模板中,存在一些可以访问的快速对象,如**handler.settings**为tornado模板中内置的环境配置信息名称,通过handler.settings可以访问到环境配置的信息。 {{handler.settings}}
SSTI类型判断
根据处理返回值的不同来进行判别,如果能识别括号内表达式的即为相应引擎
Flask SSTI漏洞
基本思路为利用 python 中的 魔术方法 找到所需函数
-
dict:保存类实例或对象实例的属性变量键值对字典
-
class:返回调用的参数类型
-
mro:返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
-
bases:返回类型列表
-
subclasses:返回object的子类
-
init:类的初始化方法
-
globals:函数会以字典类型返回当前位置的全部全局变量 与 func_globals 等价
Python里的继承关系:
已知继承关系
class A:pass
class B(A):pass 继承自A
class C(B):pass 继承自B
class D(B):pass 继承自B
c=C()
(c.__class__)(当前类C)
(c.__class__.__base__)(当前类C的父类B)
(c.__class__.__base__.__base__)(父类A)
(c.__class__.__base__.__base__.__base__)(object类)
(c.__class__.__base__.__subclasses__())(罗列出父类B下所有子类,即类C和类D)
print(c.__class__.__base__.__subclasses__()[1])(如果类C排在类D前面,这里就是调用父类B下的子类D,如果[1]换成[0]就是调用子类C)
{{''.class__}}的两个单引号意为任意对象,与{{().class__}}、{{"".class__}}或者{{[].class__}}之间区别只是包裹的是字符,元组还是列表,仅是返回的数据类型不同,本质无区别,如果被过滤可以互相替代
WAF绕过
一、{%%}绕过过滤{{}}:
二、getitem()绕过[]过滤:
三、绕过下划线过滤:
1.request方法
2、使用Unicode编码
3、使用十六进制编码
4、同理有base64编码绕过
5、格式化字符串
四、绕过点过滤:
1、[]代替点
2、attr()绕过
length(): 获取一个序列或者字典的长度并将其返回
int(): 将值转换为int类型;
float(): 将值转换为float类型
lower(): 将字符串转换为小写
upper(): 将字符串转换为大写
reverse(): 反转字符串;
replace(value,old,new): 将value中的old替换为new
list(): 将变量转换为列表类型,
string(): 将变量转换成字符串类型
join(): 将一个序列中的参数值拼接成字符串,通常配合dict()混合绕过
attr(): 获取对象的属性
详细: