Python里pickle序列化 對(duì)象序列化模塊pickle的安全隱患解析

pickle存在安全隱患的原因是反序列化時(shí)會(huì)執(zhí)行任意代碼。pickle模塊用于將python對(duì)象轉(zhuǎn)換為字節(jié)流以便存儲(chǔ)或傳輸,但加載不可信數(shù)據(jù)時(shí)可能觸發(fā)惡意指令。例如攻擊者可通過(guò)構(gòu)造特殊對(duì)象,在反序列化時(shí)調(diào)用系統(tǒng)命令。常見(jiàn)風(fēng)險(xiǎn)場(chǎng)景包括網(wǎng)絡(luò)傳輸、緩存機(jī)制及日志配置文件中誤用pickle格式。為安全使用pickle應(yīng)做到:1.僅加載可信來(lái)源的pickle文件;2.避免用其做跨語(yǔ)言通信;3.對(duì)輸入數(shù)據(jù)進(jìn)行簽名驗(yàn)證;4.在沙箱環(huán)境中加載pickle;5.優(yōu)先選用json等更安全的替代格式。總之務(wù)必遵循原則“永遠(yuǎn)不要加載你不信任的數(shù)據(jù)”。

python中,pickle 是一個(gè)常用的對(duì)象序列化模塊,可以將復(fù)雜的Python對(duì)象轉(zhuǎn)換為字節(jié)流,便于存儲(chǔ)或傳輸。但如果你從不可信的來(lái)源加載了 pickle 數(shù)據(jù),那可能會(huì)帶來(lái)嚴(yán)重的安全隱患。

什么是Pickle序列化?

Pickle 模塊的作用是“把Python對(duì)象變成一串字節(jié)”,這個(gè)過(guò)程叫做序列化。它非常適合用于保存程序運(yùn)行時(shí)的狀態(tài),比如緩存數(shù)據(jù)、保存模型參數(shù)等。使用起來(lái)也非常簡(jiǎn)單:

import pickle  data = {"name": "Alice", "age": 30} with open("data.pkl", "wb") as f:     pickle.dump(data, f)

讀取的時(shí)候也是一樣方便:

with open("data.pkl", "rb") as f:     loaded_data = pickle.load(f)

看起來(lái)很美好,但問(wèn)題就出在反序列化(load)這一步。

立即學(xué)習(xí)Python免費(fèi)學(xué)習(xí)筆記(深入)”;


Pickle為什么存在安全隱患?

核心問(wèn)題是:pickle 在反序列化時(shí)會(huì)執(zhí)行任意代碼

它不僅還原數(shù)據(jù),還會(huì)嘗試重建對(duì)象,包括調(diào)用構(gòu)造函數(shù)和自定義的 __reduce__ 方法。這就意味著,攻擊者可以通過(guò)構(gòu)造惡意的 .pkl 文件,在你加載文件時(shí)執(zhí)行任意命令,比如刪除文件、竊取信息甚至遠(yuǎn)程連接。

舉個(gè)簡(jiǎn)單的例子:

import os import pickle  class MaliciousData:     def __reduce__(self):         return (os.system, ("rm -rf /tmp/test",))  mal_data = pickle.dumps(MaliciousData()) # 如果你不小心加載了這個(gè)數(shù)據(jù)…… pickle.loads(mal_data)

一旦執(zhí)行了上面的 pickle.loads,就會(huì)執(zhí)行 rm -rf /tmp/test 命令。這就是所謂的“反序列化漏洞”。


什么場(chǎng)景下容易踩坑?

  1. 網(wǎng)絡(luò)傳輸中使用了Pickle
    有些人為了方便,直接通過(guò)網(wǎng)絡(luò)傳輸 pickle.dumps() 的結(jié)果。如果對(duì)方不可信,或者中間有人篡改數(shù)據(jù)包,就可能觸發(fā)惡意代碼。

  2. 緩存機(jī)制中用了Pickle文件
    比如用 pickle 存儲(chǔ)用戶提交的數(shù)據(jù),之后再加載回來(lái)。如果有攻擊者上傳了一個(gè)惡意構(gòu)造的 .pkl 文件,服務(wù)器加載時(shí)就會(huì)被攻擊。

  3. 日志或配置文件中誤用了Pickle格式
    雖然不常見(jiàn),但如果某些系統(tǒng)組件寫(xiě)入了可被用戶修改的 .pkl 文件,并由高權(quán)限進(jìn)程加載,也可能成為攻擊入口。


如何安全地使用Pickle?

如果你確實(shí)需要使用 pickle,可以考慮以下幾個(gè)建議:

  • ? 只加載你自己生成的Pickle文件,避免處理外部輸入。
  • ? 不要用Pickle做跨語(yǔ)言通信,它不是通用協(xié)議。
  • ? 對(duì)輸入進(jìn)行簽名驗(yàn)證,確保數(shù)據(jù)未被篡改。
  • ? 使用沙箱環(huán)境加載Pickle,限制執(zhí)行權(quán)限。
  • ? 替代方案優(yōu)先選JSON、YAML、MessagePack等更安全的格式,除非必須保留Python對(duì)象結(jié)構(gòu)。

如果你一定要接收外部的Pickle數(shù)據(jù),可以考慮自己實(shí)現(xiàn)一個(gè)白名單式的反序列化解析器,或者使用像 dill 這樣的庫(kù),雖然它們也不是絕對(duì)安全。


總結(jié)一下

Pickle 很方便,但它不是用來(lái)處理不可信數(shù)據(jù)的工具。只要記住一句話:“永遠(yuǎn)不要加載你不信任的數(shù)據(jù)”,就能避免大多數(shù)問(wèn)題。
基本上就這些。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊8 分享