0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python中的十個安全陷阱(一)

python爬蟲知識分享 ? 來源:python爬蟲知識分享 ? 作者:python爬蟲知識分享 ? 2022-03-24 16:42 ? 次閱讀

Python 開發(fā)者們在使用標準庫和通用框架時,都以為自己的程序具有可靠的安全性。然而,在 Python 中,就像在任何其它編程語言中一樣,有一些特性可能會被開發(fā)者們誤解或誤用。通常而言,只有極少的微妙之處或細節(jié)會使開發(fā)者們疏忽大意,從而在代碼中引入嚴重的安全漏洞。

在這篇博文中,我們將分享在實際 Python 項目中遇到的 10 個安全陷阱。我們選擇了一些在技術(shù)圈中不太為人所知的陷阱。通過介紹每個問題及其造成的影響,我們希望提高人們對這些問題的感知,并提高大家的安全意識。如果你正在使用這些特性,請一定要排查你的 Python 代碼!

1.被優(yōu)化掉的斷言

Python 支持以優(yōu)化的方式執(zhí)行代碼。這使代碼運行得更快,內(nèi)存用得更少。當程序被大規(guī)模使用,或者可用的資源很少時,這種方法尤其有效。一些預打包的 Python 程序提供了優(yōu)化的字節(jié)碼。

然而,當代碼被優(yōu)化時,所有的 assert 語句都會被忽略。開發(fā)者有時會使用它們來判斷代碼中的某些條件。例如,如果使用斷言來作身份驗證檢查,則可能導致安全繞過。

defsuperuser_action(request,user):
assertuser.is_super_user
#executeactionassuperuser

在這個例子中,第 2 行中的 assert 語句將被忽略,導致非超級用戶也可以運行到下一行代碼。不推薦使用 assert 語句進行安全相關(guān)的檢查,但我們確實在實際的項目中看到過它們。

2. MakeDirs 權(quán)限

os.makdirs 函數(shù)可以在操作系統(tǒng)中創(chuàng)建一個或多個文件夾。它的第二個參數(shù) mode 用于指定創(chuàng)建的文件夾的默認權(quán)限。在下面代碼的第 2 行中,文件夾 A/B/C 是用 rwx------ (0o700) 權(quán)限創(chuàng)建的。這意味著只有當前用戶(所有者)擁有這些文件夾的讀、寫和執(zhí)行權(quán)限。

definit_directories(request):
os.makedirs("A/B/C",mode=0o700)
returnHttpResponse("Done!")

在 Python < 3.6 版本中,創(chuàng)建出的文件夾 A、B 和 C 的權(quán)限都是 700。但是,在 Python > 3.6 版本中,只有最后一個文件夾 C 的權(quán)限為 700,其它文件夾 A 和 B 的權(quán)限為默認的 755。

因此,在 Python > 3.6 中,os.makdirs 函數(shù)等價于 Linux 的這條命令:mkdir -m 700 -p A/B/C。有些開發(fā)者沒有意識到版本之間的差異,這已經(jīng)在 Django 中造成了一個權(quán)限越級漏洞(cve - 2022 -24583),無獨有偶,這在 WordPress 中也造成了一個加固繞過問題。

3.絕對路徑拼接

os.path.join(path, *paths) 函數(shù)用于將多個文件路徑連接成一個組合的路徑。第一個參數(shù)通常包含了基礎(chǔ)路徑,而之后的每個參數(shù)都被當做組件拼接到基礎(chǔ)路徑后。

然而,這個函數(shù)有一個少有人知的特性。如果拼接的某個路徑以 / 開頭,那么包括基礎(chǔ)路徑在內(nèi)的所有前綴路徑都將被刪除,該路徑將被視為絕對路徑。下面的示例揭示了開發(fā)者可能遇到的這個陷阱。

defread_file(request):
filename=request.POST['filename']
file_path=os.path.join("var","lib",filename)
iffile_path.find(".")!=-1:
    returnHttpResponse("Failed!")
withopen(file_path)asf:
    returnHttpResponse(f.read(),content_type='text/plain')

在第 3 行中,我們使用 os.path.join 函數(shù)將用戶輸入的文件名構(gòu)造出目標路徑。在第 4 行中,檢查生成的路徑是否包含”.“,防止出現(xiàn)路徑遍歷漏洞。

但是,如果攻擊者傳入的文件名參數(shù)為”/a/b/c.txt“,那么第 3 行得到的變量 file_path 會是一個絕對路徑(/a/b/c.txt)。即 os.path.join 會忽略掉”var/lib“部分,攻擊者可以不使用“.”字符就讀取到任何文件。盡管 os.path.join 的文檔中描述了這種行為,但這還是導致了許多漏洞(Cuckoo Sandbox Evasion, CVE-2020-35736)。

4. 任意的臨時文件

tempfile.NamedTemporaryFile 函數(shù)用于創(chuàng)建具有特定名稱的臨時文件。但是,prefix(前綴)和 suffix(后綴)參數(shù)很容易受到路徑遍歷攻擊(Issue 35278)。如果攻擊者控制了這些參數(shù)之一,他就可以在文件系統(tǒng)中的任意位置創(chuàng)建出一個臨時文件。下面的示例揭示了開發(fā)者可能遇到的一個陷阱。

def touch_tmp_file(request):
    id = request.GET['id']
    tmp_file = tempfile.NamedTemporaryFile(prefix=id)
    return HttpResponse(f"tmp file: {tmp_file} created!", content_type='text/plain')

在第 3 行中,用戶輸入的 id 被當作臨時文件的前綴。如果攻擊者傳入的 id 參數(shù)是“/../var/www/test”,則會創(chuàng)建出這樣的臨時文件:/var/www/test_zdllj17。粗看起來,這可能是無害的,但它會為攻擊者創(chuàng)造出挖掘更復雜的漏洞的基礎(chǔ)。

5.擴展的 Zip Slip

在 Web 應用中,通常需要解壓上傳后的壓縮文件。在 Python 中,很多人都知道 TarFile.extractall 與 TarFile.extract 函數(shù)容易受到 Zip Slip 攻擊。攻擊者通過篡改壓縮包中的文件名,使其包含路徑遍歷(../)字符,從而發(fā)起攻擊。

這就是為什么壓縮文件應該始終被視為不受信來源的原因。zipfile.extractall 與 zipfile.extract 函數(shù)可以對 zip 內(nèi)容進行清洗,從而防止這類路徑遍歷漏洞。

但是,這并不意味著在 ZipFile 庫中不會出現(xiàn)路徑遍歷漏洞。下面是一段解壓縮文件的代碼。

def extract_html(request):
    filename = request.FILES['filename']
    zf = zipfile.ZipFile(filename.temporary_file_path(), "r")
    for entry in zf.namelist():
        if entry.endswith(".html"):
            file_content = zf.read(entry)
            with open(entry, "wb") as fp:
                fp.write(file_content)
    zf.close()
    return HttpResponse("HTML files extracted!")

第 3 行代碼根據(jù)用戶上傳文件的臨時路徑,創(chuàng)建出一個 ZipFile 處理器。第 4 - 8 行代碼將所有以“.html”結(jié)尾的壓縮項提取出來。第 4 行中的 zf.namelist 函數(shù)會取到 zip 內(nèi)壓縮項的名稱。注意,只有 zipfile.extract 與 zipfile.extractall 函數(shù)會對壓縮項進行清洗,其它任何函數(shù)都不會。

在這種情況下,攻擊者可以創(chuàng)建一個文件名,例如“../../../var/www/html”,內(nèi)容隨意填。該惡意文件的內(nèi)容會在第 6 行被讀取,并在第 7-8 行寫入被攻擊者控制的路徑。因此,攻擊者可以在整個服務器上創(chuàng)建任意的 HTML 文件。

如上所述,壓縮包中的文件應該被看作是不受信任的。如果你不使用 zipfile.extractall 或者 zipfile.extract,你就必須對 zip 內(nèi)文件的名稱進行“消毒”,例如使用 os.path.basename。否則,它可能導致嚴重的安全漏洞,就像在 NLTK Downloader (CVE-2019-14751)中發(fā)現(xiàn)的那樣。
審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 程序
    +關(guān)注

    關(guān)注

    116

    文章

    3766

    瀏覽量

    80767
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4728

    瀏覽量

    68250
  • python
    +關(guān)注

    關(guān)注

    55

    文章

    4774

    瀏覽量

    84386
收藏 人收藏

    評論

    相關(guān)推薦

    具有十個解碼輸出的進位計數(shù)器/除法器數(shù)據(jù)表

    電子發(fā)燒友網(wǎng)站提供《具有十個解碼輸出的進位計數(shù)器/除法器數(shù)據(jù)表.pdf》資料免費下載
    發(fā)表于 05-17 10:47 ?0次下載
    具有<b class='flag-5'>十個</b>解碼輸出的<b class='flag-5'>十</b>進位計數(shù)器/除法器數(shù)據(jù)表

    ADIS16460正常的工作溫度是?25°C 到 +85°C,為什么測試的時候有幾十個是-10°C ?

    ADIS16460正常的工作溫度是?25°C 到 +85°C,為什么測試的時候有幾十個是-10°C ?
    發(fā)表于 12-28 08:18

    split在python的用法

    split在python的用法 split()是Python非常常用的字符串函數(shù),它能夠根據(jù)指定的分隔符將
    的頭像 發(fā)表于 12-25 15:12 ?1951次閱讀

    華為星閃BS25 SDKGADC設(shè)置的陷阱

    用華為星閃 BS25 SDK 做產(chǎn)品中發(fā)現(xiàn) GADC陷阱。
    的頭像 發(fā)表于 12-01 14:01 ?1561次閱讀
    華為星閃BS25 SDK<b class='flag-5'>中</b>GADC設(shè)置的<b class='flag-5'>陷阱</b>

    python如何修改列表的每一個值數(shù)據(jù)

    Python,我們可以使用不同的方法來修改列表的每一個值數(shù)據(jù)。 方法:使用for循環(huán)遍歷列表并修改元素值 首先,我們可以使用for循
    的頭像 發(fā)表于 11-29 17:03 ?4757次閱讀

    Python2與Python3的差異

    Python2,print語句是關(guān)鍵字,而在Python3,print函數(shù)被引入,必須使
    的頭像 發(fā)表于 11-23 16:48 ?880次閱讀

    python如何直循環(huán)代碼

    Python,有幾種方法可以實現(xiàn)代碼的循環(huán)執(zhí)行。下面我將詳盡、詳實、細致地介紹這些方法和它們的使用情況。 使用while循環(huán): 在Python,可以使用while循環(huán)來重復執(zhí)行
    的頭像 發(fā)表于 11-23 15:54 ?2457次閱讀

    pythontext的用法

    Python的text是常見的數(shù)據(jù)類型,它用于存儲和處理文本數(shù)據(jù)。在Python,文本常
    的頭像 發(fā)表于 11-23 15:46 ?3274次閱讀

    pythoninput怎么輸入3

    Python ,可以使用 input() 函數(shù)來獲取用戶的輸入。如果你想要輸入多個值,可以根據(jù)具體的需求使用以下方法。 方法:使用多個 input 函數(shù) 最簡單的方法是使用多個 input
    的頭像 發(fā)表于 11-23 15:31 ?9477次閱讀

    pythonnumber代表什么

    Python,number(數(shù)字)是種內(nèi)置的數(shù)據(jù)類型,用于表示數(shù)值。Python提供了幾種不同的number類型,分別是整數(shù)(int)、浮點數(shù)(float)、復數(shù)(complex
    的頭像 發(fā)表于 11-22 09:50 ?1840次閱讀

    Python如何表達復數(shù)

    Python,可以使用complex類型來表示和操作復數(shù)。復數(shù)是由實部和虛部組成的數(shù)
    的頭像 發(fā)表于 11-21 16:50 ?2082次閱讀

    pythonif三條件怎么寫

    Python ,使用 if 語句可以根據(jù)給定條件的真假來決定程序的執(zhí)行路徑。通常情況下,if 語句有條件,并根據(jù)這個條件來判斷是否執(zhí)行某段代碼。然而,在某些情況下,我們需要根
    的頭像 發(fā)表于 11-21 16:42 ?1311次閱讀

    python輸出list的每一個元素

    使用for循環(huán)來遍歷列表,并輸出其中的每一個元素。接下來,我將詳盡、詳實、細致地介紹Python輸出列表的每一個元素的方法,希望能對你有所幫助。 首先,我們需要明確
    的頭像 發(fā)表于 11-21 16:16 ?1439次閱讀

    接口調(diào)用并發(fā)執(zhí)行十個任務總結(jié)

    接口調(diào)用時,接收到列表,十個元素,需要并發(fā)執(zhí)行十個任務,每個任務都要返回執(zhí)行的結(jié)果和異常
    的頭像 發(fā)表于 11-15 10:37 ?412次閱讀

    python如何定義函數(shù)

    Python3 函數(shù) 函數(shù)是組織好的,可重復使用的,用來實現(xiàn)單,或相關(guān)聯(lián)功能的代碼段。 函數(shù)能提高應用的模塊性,和代碼的重復利用率。你已經(jīng)知道Python提供了許多內(nèi)建函數(shù),比如
    的頭像 發(fā)表于 11-14 11:26 ?673次閱讀