編寫安全代碼很難。當(dāng)您學(xué)習(xí)一種語(yǔ)言,一種模塊或一種框架時(shí),您將了解應(yīng)該如何使用它。考慮安全性時(shí),您需要考慮如何濫用它。Python也不例外,即使在標(biāo)準(zhǔn)庫(kù)中,也記錄了編寫強(qiáng)化應(yīng)用程序的不良做法。但是,當(dāng)我與許多Python開發(fā)人員交談時(shí),他們根本不了解他們。今天本文主要介紹的是Python中的10個(gè)常見安全陷阱以及避免方法的信息。
1.輸入注入
注入攻擊非常廣泛并且確實(shí)很常見,并且注入的類型很多。它們影響所有語(yǔ)言,框架和環(huán)境。
SQL注入是直接編寫SQL查詢而不是使用ORM并將字符串文字與變量混合的地方。我讀了很多代碼,其中“轉(zhuǎn)義引號(hào)”被認(rèn)為是解決方法。不是,熟悉此備忘單可進(jìn)行SQL注入的所有復(fù)雜方式。
您可以在使用popen,子進(jìn)程,os.system并從變量獲取參數(shù)的任何時(shí)候調(diào)用命令注入。調(diào)用本地命令時(shí),有人可能會(huì)將這些值設(shè)置為惡意內(nèi)容。
想象一下這個(gè)簡(jiǎn)單的腳本[credit]。您使用用戶提供的文件名調(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!
避免方法:
如果使用的是Web框架隨附的實(shí)用程序,則對(duì)輸入內(nèi)容進(jìn)行清理。除非您有充分的理由,否則不要手動(dòng)構(gòu)造SQL查詢。大多數(shù)ORM具有內(nèi)置的消毒方法。
對(duì)于外殼,請(qǐng)使用shlex模塊正確地轉(zhuǎn)義輸入。
2.解析XML
如果您的應(yīng)用程序曾經(jīng)加載并解析XML文件,則很可能您正在使用XML標(biāo)準(zhǔn)庫(kù)模塊之一。通過(guò)XML有一些常見的攻擊。大多是DoS風(fēng)格的。這些攻擊很常見,尤其是當(dāng)您解析外部XML文件時(shí)。
其中之一被稱為“十億個(gè)笑聲”,因?yàn)橛行лd荷通常包含很多“笑聲”。基本上,您的想法是可以使用XML進(jìn)行引用實(shí)體,因此,當(dāng)您不使用XML的解析器嘗試將此XML文件加載到內(nèi)存中時(shí),它將占用數(shù)GB的RAM。
另一種攻擊是使用外部實(shí)體擴(kuò)展。XML支持從外部URL引用實(shí)體,XML解析器通常會(huì)毫無(wú)限制地獲取和加載該資源。“攻擊者可以繞過(guò)防火墻并獲得對(duì)受限資源的訪問(wèn)權(quán)限,因?yàn)樗姓?qǐng)求都是從內(nèi)部可信賴的IP地址發(fā)出的,而不是從外部發(fā)出的。”
要考慮的另一種情況是您依賴于解碼XML的第三方包,例如配置文件,遠(yuǎn)程API。您甚至可能沒(méi)有意識(shí)到,您的依賴項(xiàng)之一使自己容易受到這些類型的攻擊。
避免方法:
使用defusedxml替代標(biāo)準(zhǔn)庫(kù)模塊。它增加了針對(duì)這些類型攻擊的安全防護(hù)。
3.聲明
不要使用assert語(yǔ)句來(lái)防止用戶不應(yīng)訪問(wèn)的代碼段。以這個(gè)簡(jiǎn)單的例子
def foo(request,user):
斷言u(píng)ser.is_admin,“用戶無(wú)權(quán)訪問(wèn)”
#安全代碼...
現(xiàn)在,默認(rèn)情況下,Python以__debug__true的身份執(zhí)行,但是在生產(chǎn)環(huán)境中,通常會(huì)運(yùn)行優(yōu)化。這將跳過(guò)assert語(yǔ)句,并直接轉(zhuǎn)到安全代碼,而不管用戶is_admin與否。
避免方法:
僅使用assert語(yǔ)句與其他開發(fā)人員進(jìn)行通信,例如在單元測(cè)試中或在防止API使用不正確的情況下。
4.定時(shí)攻擊
定時(shí)攻擊本質(zhì)上是一種通過(guò)定時(shí)比較提供的值所花費(fèi)的時(shí)間來(lái)揭示行為和算法的方法。定時(shí)攻擊需要精度,因此它們通常無(wú)法在高延遲的遠(yuǎn)程網(wǎng)絡(luò)上工作。由于大多數(shù)Web應(yīng)用程序涉及可變的延遲,因此在HTTP Web服務(wù)器上編寫定時(shí)攻擊幾乎是不可能的。
但是,如果您有一個(gè)提示輸入密碼的命令行應(yīng)用程序,則攻擊者可以編寫一個(gè)簡(jiǎn)單的腳本來(lái)確定將其值與實(shí)際機(jī)密進(jìn)行比較所花費(fèi)的時(shí)間。
避免方法:
使用secrets.compare_digest ,在Python 3.5引入了比較密碼和其他個(gè)人價(jià)值。
5.污染的站點(diǎn)包或?qū)肼窂?/strong>
Python的導(dǎo)入系統(tǒng)非常靈活。當(dāng)您嘗試為測(cè)試編寫猴子補(bǔ)丁或重載核心功能時(shí),這很棒。
但是,這是Python中最大的安全漏洞之一。
無(wú)論在虛擬環(huán)境中還是在全局站點(diǎn)程序包(通常不鼓勵(lì)使用)中,將第3方程序包安裝到您的站點(diǎn)程序包中都會(huì)使您面臨這些程序包中的安全漏洞。
出現(xiàn)了一些與流行的軟件包名稱相似但發(fā)布到PyPi的軟件包,但是會(huì)執(zhí)行任意代碼。幸運(yùn)的是,最大的事件沒(méi)有害處,只是“指出”該問(wèn)題并未得到真正解決。
要考慮的另一種情況是您的依存關(guān)系(依此類推)。它們可能包括漏洞,也可能會(huì)通過(guò)導(dǎo)入系統(tǒng)覆蓋Python中的默認(rèn)行為。
避免方法:
審核您的包裹。查看PyUp.io及其安全服務(wù)。對(duì)所有應(yīng)用程序使用虛擬環(huán)境,并確保您的全局站點(diǎn)程序包盡可能干凈。檢查包簽名。
6.臨時(shí)文件
要在Python中創(chuàng)建臨時(shí)文件,通常需要使用mktemp()函數(shù)生成文件名,然后使用該名稱創(chuàng)建文件。“這是不安全的,因?yàn)樵诘谝粋€(gè)進(jìn)程調(diào)用到隨后嘗試創(chuàng)建該文件之間的時(shí)間內(nèi),不同的進(jìn)程可能會(huì)使用該名稱mktemp()創(chuàng)建文件。” [1]這意味著它可能會(huì)欺騙您的應(yīng)用程序以加載錯(cuò)誤的數(shù)據(jù)或公開其他臨時(shí)數(shù)據(jù)。
如果調(diào)用不正確的方法,Python的最新版本將發(fā)出運(yùn)行時(shí)警告。
避免方法:
使用該tempfile 模塊,并 mkstemp在需要生成臨時(shí)文件時(shí)使用。
7.使用yaml.load
引用PyYAML文檔:
警告:yaml.load從不可信來(lái)源收到的任何數(shù)據(jù)都無(wú)法打電話。yaml.load具有強(qiáng)大的功能pickle.load,因此可以調(diào)用任何Python函數(shù)。”
這個(gè)美麗的例子在流行的Python項(xiàng)目Ansible中找到。您可以為Ansible Vault提供此值作為有效YAML。它os.system()使用文件中提供的參數(shù)進(jìn)行調(diào)用。
python/object/apply:os.system ["cat /etc/passwd"]
因此,從用戶提供的值有效加載YAML文件可讓您敞開大門進(jìn)行攻擊。
避免方法:
yaml.safe_load除非您有充分的理由,否則幾乎總是使用。
8.泡菜
反序列化泡菜數(shù)據(jù)與YAML一樣糟糕。Python類可以聲明一個(gè)魔術(shù)方法__reduce__,該方法返回一個(gè)字符串,或者聲明一個(gè)具有可調(diào)用項(xiàng)的元組,以及在腌制時(shí)要調(diào)用的參數(shù)。攻擊者可以使用它來(lái)包含對(duì)子流程模塊之一的引用,以在主機(jī)上運(yùn)行任意命令。
這個(gè)奇妙的示例顯示了如何腌制在Python 2中打開外殼程序的類。還有更多有關(guān)如何利用腌制的示例。
導(dǎo)入cPickle
導(dǎo)入子進(jìn)程
導(dǎo)入base64
類RunBinSh(object):
def __reduce __(self):
return(subprocess.Popen ,(('/ bin / sh',),))
打印base64.b64encode(cPickle.dumps(RunBinSh()) )
避免方法:
切勿從不可信或未經(jīng)身份驗(yàn)證的源中獲取數(shù)據(jù)。請(qǐng)改用其他序列化模式,例如JSON。
9.使用系統(tǒng)Python運(yùn)行時(shí)而不進(jìn)行修補(bǔ)
大多數(shù)POSIX系統(tǒng)都帶有Python 2版本。通常是一個(gè)舊版本。
由于“ Python”即CPython。是用C編寫的,因此Python解釋器本身有時(shí)會(huì)有漏洞。C語(yǔ)言中的常見安全問(wèn)題與內(nèi)存分配有關(guān),因此存在緩沖區(qū)溢出錯(cuò)誤。
多年來(lái),CPython擁有許多溢出或溢出漏洞,每個(gè)漏洞都已在后續(xù)發(fā)行版中進(jìn)行了修補(bǔ)和修復(fù)。
所以你很安全。也就是說(shuō),如果您修補(bǔ)運(yùn)行時(shí)。
這是2.7.13及以下版本的示例,它是一個(gè)整數(shù)溢出漏洞,可啟用代碼執(zhí)行。這幾乎是Ubuntu 17之前的任何未修補(bǔ)版本。
避免方法:
為您的生產(chǎn)應(yīng)用程序安裝最新版本的Python,然后對(duì)其進(jìn)行修補(bǔ)。
10.不打補(bǔ)丁
與不修補(bǔ)運(yùn)行時(shí)類似,您還需要定期修補(bǔ)依賴項(xiàng)。
我發(fā)現(xiàn)在PyPi中“避免方法” Python軟件包版本的做法令人恐懼。這個(gè)想法是“ 這些是可行的版本 ”,因此每個(gè)人都將其保留。
我上面提到的代碼中的所有漏洞在應(yīng)用程序使用的程序包中都存在時(shí)同樣重要。這些軟件包的開發(fā)人員修復(fù)了安全性問(wèn)題。
避免方法:
使用PyUp.io之類的服務(wù)來(lái)檢查更新,向應(yīng)用程序提出拉/合并請(qǐng)求并運(yùn)行測(cè)試以使程序包保持最新。
使用InSpec之類的工具可以在生產(chǎn)環(huán)境中驗(yàn)證安裝的版本,并確保修補(bǔ)了最小的版本或版本范圍。
以上就是關(guān)于Python中的10個(gè)常見安全陷阱以及避免方法的全部?jī)?nèi)容介紹,想了解更多關(guān)于Python的信息,請(qǐng)繼續(xù)關(guān)注我們。