沙盒逃逸
在做中海的一道题,学长看一眼说是沙盒逃逸了,这里就过来看看
题目给了一个python环境,这里就具体看python沙盒逃逸
python沙盒逃逸
沙箱逃逸就是在在一个严格限制的python环境中,通过绕过限制和过滤达到执行更高权限,甚至getshell的过程
Python 的沙箱逃逸的最终目标就是执行系统任意命令,次一点的写文件,再次一点的读文件
既然我们需要命令执行,那么我们就需要了解一下python中能执行系统命令的方法,既然是执行命令,常见调用的模块就是os (sys pty subprocess plarform commands 这些模块也可以调用进行命令执行,但没有具体试过,所所以这里先简单列举出来),有时不需要文件执行,只需要读取文件时,可以直接利用open file等文件读取模块
题目给出了配置文件
1 | from flask import * |
这里可以看到他的黑名单里过滤了很多常见的函数,而在沙盒逃逸中最常见的过滤就是过滤import,从而限制模块的调入
这道题限制的其实不是很多,但主要是我们需要去打开配置文件时发现app.py不存在,这里思路断了(看题目给出的提示后更懵了)
他的错误提示是不存app.py,说明前面的函数仍然可以调用,前面的语句应该是没有问题的,重点就来到了如何在没有app.py的情况下,读取配置文件,又去简单看一了proc 和 /etc/paaswd发现都被删干净了,思路彻底断了
所以重点学习一下python沙盒逃逸的知识点
对于import的导入限制绕过方法,其实绕过的方法也是比较多的
1 | __import__ |
还有的就是通过一些简单的拼接和加密绕过(字符串翻转,字符串拼接,base64加密)
再者还可以使用execfile,execfile需要知道库的物理路径(物理路径可以通过sys来获取)
1 | f = open(r'/usr/lib/python3.6/os.py','r') |
1 | with open('/usr/lib/python3.6/os.py','r') as f: |
还有其他乱七八糟的,这里都可以试试,反正就是导入需要的库即可
导入库只是第一步,这里还需要调用命令执行的函数
除了常见的system popen 还可以通过getattr 拿到对象的方法、属性
1 | import os |
不让出现 import 也没事
1 | getattr(getattr(__builtins__, '__tropmi__'[::-1])('so'[::-1]), 'metsys'[::-1])('whoami') |
我们在学ssti的时候,经常会在字典里调用一个键值为__builtins__
,而这个模块就是内建模块,多函数不需要任何 import 就可以直接使用,例如chr
、open
,这些函数都是放在这个模块下,有必要时可以通过这个模块进行导入
1 | __builtins__.__dict__['__import__']('os').system('whoami') |
但当__builtins__
模块中的函数被破坏的时候我们可以利用 reload(__builtins__)
来恢复 __builtins__
通过继承关系逃逸
我们逃逸不仅可以通过绕过来进行,同时也可以通过继承关系来进行
python是支持多重继承的,也就是可以拥有多个父类
python中类都有个属性(mro),是一个元组,记录了类的继承关系。
当一些文件操作的函数和类型被过滤的情况下
1 | "".__class__.__mro__[-1].__subclasses__()[40](filename).read() |
总结而言:
1.通过__class__、mro、subclasses、__bases__
等等属性/方法去获取 object.
2.根据__globals__
找引入的__builtins__
或者eval
等等能够直接被利用的库,或者找到builtin_function_or_method类/类型
3.__call__
后直接运行eval
还有一些就是对一些符号和特殊字符什么的绕过,这里就等到具体题目做到再来写
这篇文章总体就是队python沙盒逃逸做一个了解,个人感觉沙盒逃逸就是通过绕过方法进行队文件的命令执行,而其中会碰到许多过滤,但看文章还是比较抽象的,那道题目暂时还是卡着,所以先放在这里了