一文詳解python pickle中的反序列化漏洞
1. 引言
大家好,今天我們來聊聊Python里的反序列化攻擊。先來看看什么是序列化和反序列化。簡單來說,序列化就是把數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換成字節(jié)流,這樣我們就可以把數(shù)據(jù)保存到文件里或者通過網(wǎng)絡(luò)傳輸。反序列化則是把這些字節(jié)流再轉(zhuǎn)換回原來的數(shù)據(jù)結(jié)構(gòu)。
在Python里,常用的模塊之一就是Pickle。它可以幫我們很方便地進行序列化和反序列化操作。比如,你可以把一個復(fù)雜的Python對象序列化保存下來,等需要用的時候再反序列化回來。
反序列化攻擊的概述
反序列化過程有漏洞:如果我們反序列化了一個不可信的數(shù)據(jù)源,那就可能引發(fā)反序列化攻擊。攻擊者可以在序列化的數(shù)據(jù)里嵌入惡意代碼,當你反序列化這個數(shù)據(jù)時,這些惡意代碼就會被執(zhí)行,可能會導(dǎo)致數(shù)據(jù)泄露、系統(tǒng)崩潰,甚至讓攻擊者遠程控制你的系統(tǒng)。
2. Python Pickle模塊概述
Pickle的基本功能
Pickle模塊是Python自帶的,它主要用來序列化和反序列化Python對象。你可以用Pickle把任何Python對象(包括復(fù)雜的數(shù)據(jù)結(jié)構(gòu))保存成字節(jié)流,然后在需要的時候再加載回來。
Pickle的工作原理
Pickle的工作原理其實很簡單。序列化的時候,它會把Python對象轉(zhuǎn)換成字節(jié)流,反序列化的時候,它會把字節(jié)流還原成Python對象。下面我們來看幾個具體的例子。
Pickle的序列化與反序列化
序列化
序列化就是把Python對象轉(zhuǎn)換成字節(jié)流。我們可以用pickle.dump
和pickle.dumps
來做這件事。pickle.dump
把對象序列化后寫入文件,pickle.dumps
則返回一個字節(jié)流。
import pickle # 創(chuàng)建一個對象 data = {'name': 'Alice', 'age': 25, 'city': 'New York'} # 序列化對象并寫入文件 with open('data.pickle', 'wb') as file: pickle.dump(data, file) # 或者返回一個字節(jié)流 data_bytes = pickle.dumps(data)
反序列化
反序列化就是把字節(jié)流還原成Python對象。我們可以用pickle.load
和pickle.loads
來做這件事。pickle.load
從文件中讀取字節(jié)流并反序列化,pickle.loads
則直接反序列化一個字節(jié)流。
import pickle # 從文件中反序列化對象 with open('data.pickle', 'rb') as file: data = pickle.load(file) # 或者直接反序列化一個字節(jié)流 data = pickle.loads(data_bytes)
3. 反序列化攻擊的原理
攻擊機制
現(xiàn)在我們來看看反序列化攻擊是怎么回事。攻擊者可以在序列化的數(shù)據(jù)里嵌入惡意代碼,當你反序列化這個數(shù)據(jù)時,這些惡意代碼就會被執(zhí)行。換句話說,如果你從不可信的數(shù)據(jù)來源反序列化數(shù)據(jù),就等于是給了攻擊者在你系統(tǒng)里執(zhí)行代碼的機會。
攻擊者可以做什么
攻擊者可以利用反序列化漏洞執(zhí)行任意命令、修改或竊取數(shù)據(jù)。
示例代碼
為了更清楚地說明問題,我們來看一個簡單的反序列化攻擊示例。
import pickle import os # 構(gòu)造惡意代碼 class Malicious: def __reduce__(self): return (os.system, ('echo Hacked!',)) # 序列化惡意對象 malicious_data = pickle.dumps(Malicious()) # 反序列化時執(zhí)行惡意代碼 pickle.loads(malicious_data)
在這個示例中,我們創(chuàng)建了一個名為Malicious
的類。這個類的__reduce__
方法返回一個元組,第一個元素是os.system
,第二個元素是要執(zhí)行的命令。當我們反序列化這個對象時,os.system('echo Hacked!')
會被執(zhí)行,輸出“Hacked!”。
詳細解釋
- 構(gòu)造惡意代碼:我們定義了一個
Malicious
類,并在__reduce__
方法中指定要執(zhí)行的命令。 - 序列化惡意對象:我們用
pickle.dumps
序列化這個惡意對象。 - 反序列化惡意對象:當我們用
pickle.loads
反序列化這個對象時,__reduce__
方法會被調(diào)用,并執(zhí)行指定的命令。
4. 如何防范Pickle反序列化攻擊
安全反序列化的原則
防范反序列化攻擊的第一原則就是:避免從不可信來源反序列化。只有當你完全信任數(shù)據(jù)的來源時,才可以使用反序列化。
實際防御方法
我們來看一些具體的防御方法和代碼示例。
安全的反序列化代碼示例
如果必須使用Pickle進行反序列化,可以考慮重載find_class
來限定范圍限制反序列化的對象類型:
import pickle import types # 自定義Unpickler,限制可反序列化的類型 class RestrictedUnpickler(pickle.Unpickler): def find_class(self, module, name): if module == "builtins" and name in {"str", "list", "dict", "set", "int", "float", "bool"}: return getattr(__import__(module), name) raise pickle.UnpicklingError(f"global '{module}.{name}' is forbidden") def restricted_loads(s): return RestrictedUnpickler(io.BytesIO(s)).load()
在這個示例中,我們自定義了一個RestrictedUnpickler
類,只允許反序列化某些安全的內(nèi)置類型。
使用其他安全的序列化模塊(如JSON)
一個更安全的做法是使用JSON替代Pickle進行序列化和反序列化。JSON只支持基本數(shù)據(jù)類型,不會執(zhí)行任意代碼,因而更安全。
import json # 序列化對象 data = {'name': 'Alice', 'age': 25, 'city': 'New York'} data_json = json.dumps(data) # 反序列化對象 data = json.loads(data_json)
總結(jié)
本文說明了什么是序列化和反序列化,以及Python中的Pickle模塊。文中還詳細解釋了反序列化攻擊的原理,并給出了攻擊代碼示例。最后討論了如何防范Pickle反序列化攻擊,并提供了一些具體的防御方法。
到此這篇關(guān)于一文詳解python pickle中的反序列化漏洞的文章就介紹到這了,更多相關(guān)python pickle反序列化漏洞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Python 序列化Serialize 和 反序列化Deserialize
這篇文章主要介紹了詳解Python 序列化Serialize 和 反序列化Deserialize的相關(guān)資料,序列化是將對象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^程。與序列化相對的是反序列化,它將流轉(zhuǎn)換為對象。這兩個過程結(jié)合起來,可以輕松地存儲和傳輸數(shù)據(jù),需要的朋友可以參考下2017-08-08Python實現(xiàn)批量讀取HDF多波段柵格數(shù)據(jù)并繪制像元直方圖
這篇文章主要為大家詳細介紹了如何基于Python語言gdal模塊,實現(xiàn)多波段HDF柵格圖像文件的讀取、處理與像元值可視化(直方圖繪制)等操作,需要的可以參考一下2023-03-03python通過自定義isnumber函數(shù)判斷字符串是否為數(shù)字的方法
這篇文章主要介紹了python通過自定義isnumber函數(shù)判斷字符串是否為數(shù)字的方法,涉及Python操作字符串判斷的相關(guān)技巧,需要的朋友可以參考下2015-04-04Python打包后的exe還原成.py的實現(xiàn)步驟
本文主要介紹了Python打包后的exe還原成.py的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02