一文教你學(xué)會(huì)程序開發(fā)中的代碼審計(jì)
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
本文目錄概覽 ? 執(zhí)行代碼審查 您有時(shí)會(huì)遇到您正在攻擊的應(yīng)用程序的源代碼。例如,您可以從web應(yīng)用程序中提取JavaScript代碼,在偵察過程中找到存儲(chǔ)在服務(wù)器上的腳本,或者從Android應(yīng)用程序中獲取Java源代碼。 如果是這樣,你就很幸運(yùn)!審查代碼是發(fā)現(xiàn)應(yīng)用程序中的漏洞的最佳方法之一。 您可以在應(yīng)用程序的源代碼中直接定位不安全的編程代碼來(lái)查找漏洞,而不是通過嘗試不同的payload和攻擊來(lái)測(cè)試應(yīng)用程序。 源代碼審查不僅是一種更快的發(fā)現(xiàn)漏洞的方法,而且還可以幫助您學(xué)習(xí)如何在未來(lái)安全地編程,因?yàn)槟鷷?huì)觀察到其他人的錯(cuò)誤。 通過學(xué)習(xí)漏洞如何在源代碼中顯現(xiàn)出來(lái),您可以建立一種關(guān)于漏洞是如何以及為什么發(fā)生的直覺。學(xué)習(xí)進(jìn)行源代碼審查最終將幫助你成為一個(gè)更好的黑客。 本章介紹了幫助您開始代碼審查的策略。我們將介紹你應(yīng)該尋找什么,并通過實(shí)例詳細(xì)解釋。 請(qǐng)記住,大多數(shù)時(shí)候,您不必是一名程序員才能使用特定語(yǔ)言進(jìn)行代碼審查。 只要您理解一種編程語(yǔ)言,就可以應(yīng)用你的直覺來(lái)審查用不同語(yǔ)言編寫的各種軟件。但是了解特定目標(biāo)的語(yǔ)言和架構(gòu)可以讓你發(fā)現(xiàn)更細(xì)微的錯(cuò)誤。 如果您有興趣了解本章中提到的策略之外的更多關(guān)于代碼審計(jì)的信息,那么OWASP代碼審計(jì)指南是一個(gè)值得參考的綜合資源。
白盒vs黑盒測(cè)試 你可能聽過網(wǎng)絡(luò)安全從業(yè)者提到過黑盒測(cè)試和白盒測(cè)試。 黑盒測(cè)試是從外部測(cè)試軟件。與現(xiàn)實(shí)生活中的攻擊者一樣,這些測(cè)試人員對(duì)應(yīng)用程序的內(nèi)部邏輯基本不了解。 相比之下,在灰盒測(cè)試中,測(cè)試人員對(duì)該應(yīng)用程序的內(nèi)部結(jié)構(gòu)的了解有限。 在白盒測(cè)試中,測(cè)試人員可以完全訪問軟件的源代碼和文檔。 通常,bug賞金搜索是一個(gè)黑盒過程,因?yàn)槟鸁o(wú)法訪問應(yīng)用程序的源代碼。但是,如果您可以識(shí)別應(yīng)用程序的開源組件或找到它的源代碼,那么您就可以將您的搜索轉(zhuǎn)換為更有利的灰盒或白盒測(cè)試。 快速方法:grep Is是你最好的朋友 這里有幾種可以在源代碼中尋找漏洞的方法,取決于您想要檢查的多么詳細(xì)。 我們將從“我將拿走我可以拿走的”的策略開始。如果你想在短時(shí)間內(nèi)最大化發(fā)現(xiàn)的bug的數(shù)量,它很適用。這些技術(shù)速度很快,而且通常會(huì)使你發(fā)現(xiàn)一些最嚴(yán)重的漏洞,但它們往往忽略了更精妙的漏洞。 使用grep命令,查找已知有危險(xiǎn)的特定函數(shù)、字符串、關(guān)鍵字和代碼模式。 例如,在PHP中使用eval()函數(shù)表明可能存在代碼注入漏洞。 要了解如何操作,假設(shè)您搜索eval()并拉出以下代碼片段: 反序列化漏洞審計(jì)
在本例中,$_COOKIE['data'] 【2】檢索一個(gè)名為data的用戶cookie。 eval()函數(shù)【1】執(zhí)行PHP代碼$this->hook。 總之,這段代碼接受一個(gè)名為data的用戶cookie,并將其反序列化。該應(yīng)用程序還定義了一個(gè)名為UserFunction的類,當(dāng)反序列化時(shí),它會(huì)在類的實(shí)例對(duì)象的$hook屬性中存儲(chǔ)的字符串上運(yùn)行eval函數(shù)。 __wakeup():當(dāng)對(duì)象被反序列化時(shí)被自動(dòng)調(diào)用。 此代碼包含一個(gè)不安全的反序列化漏洞,從而導(dǎo)致了一個(gè)RCE。 這是因?yàn)樵搼?yīng)用程序從用戶的cookie中獲取用戶輸入,并直接將其插入到一個(gè)反序列化函數(shù)中。因此,用戶可以通過構(gòu)造一個(gè)序列化對(duì)象并將其傳遞到cookie中的data參數(shù),使unserialize() 啟動(dòng)應(yīng)用程序可以訪問的任何類。 您可以通過這個(gè)反序列化缺陷來(lái)實(shí)現(xiàn)RCE,因?yàn)樗鼘⒂脩籼峁┑膶?duì)象傳遞給unserialize(),并且UserFunction類在用戶提供的輸入上運(yùn)行eval,這意味著用戶可以讓應(yīng)用程序執(zhí)行任意的用戶代碼。 要利用這個(gè)RCE,您只需將cookie的data變量設(shè)置為一個(gè)序列化的UserFunction對(duì)象,并將hook屬性設(shè)置為您想要的任何PHP代碼。 您可以使用以下代碼生成序列化對(duì)象:
將上面代碼輸出的字符串傳遞到cookie的data字段將導(dǎo)致執(zhí)行代碼phpinfo。 此示例取自O(shè)WASP的PHP對(duì)象注入指南。
您可以在第14章中了解更多關(guān)于不安全的反序列化漏洞的信息。 當(dāng)您剛剛開始查看一段源代碼時(shí),請(qǐng)集中精力搜索被用戶控制的參數(shù)上使用的危險(xiǎn)函數(shù),數(shù)據(jù)表22-1列出了幾個(gè)需要注意的危險(xiǎn)函數(shù)的示例。 這些函數(shù)的存在并不能保證有漏洞,但可以提醒您注意可能存在的漏洞。 危險(xiǎn)函數(shù) php 如果使用未校驗(yàn)清洗的用戶輸入會(huì)導(dǎo)致RCE。 eval(), assert()在其輸入中執(zhí)行PHP代碼. 而system(), exec(), shell_exec(), passthru(), popen()和back-ticks執(zhí)行系統(tǒng)命令。 include(),require()可以用于執(zhí)行PHP代碼,通過向函數(shù)提供一個(gè)遠(yuǎn)程PHP腳本的url。 unserialize()如果在未校驗(yàn)清洗的用戶輸入上使用,則反序列化不安全。
Python 如果在未校驗(yàn)清洗的用戶輸入上使用eval(), exec(), os.system()函數(shù)會(huì)導(dǎo)致RCE。 如果在未校驗(yàn)清洗的用戶輸入上使用pickle.loads(), yaml.load(),會(huì)導(dǎo)致不安全的反序列化。
JavaScript 如果在document.write(), document.writeln函數(shù)中傳入未校驗(yàn)清洗的用戶輸入,會(huì)導(dǎo)致xss。 這些函數(shù)會(huì)寫入HTML文檔。因此,如果攻擊者能夠在受害者的頁(yè)面上控制傳遞到函數(shù)中的值,那么攻擊者就可以將JavaScript寫入到受害者的頁(yè)面上。 在未清洗的用戶輸入上使用document.location.href()時(shí),會(huì)造成開放重定向漏洞。 document.location.href()會(huì)更改用戶頁(yè)面的位置(url)。
Ruby 如果System(), exec(), %x(), backticks(`CODE`)函數(shù)用于未清洗的用戶輸入會(huì)造成RCE。 如果在未清洗的用戶輸入上使用Marshall.load(), yaml.load()函數(shù),則反序列化不安全。
泄露的憑證和弱加密 尋找泄露的密鑰和憑證。有時(shí),開發(fā)人員會(huì)錯(cuò)誤地將API密鑰、加密密鑰和數(shù)據(jù)庫(kù)密碼硬編碼到源代碼中。 當(dāng)源代碼泄露給攻擊者時(shí),攻擊者可以使用這些憑據(jù)來(lái)訪問公司的資產(chǎn)。 例如,我在web應(yīng)用程序的JavaScript文件中找到了硬編碼的API密鑰。 您可以通過grep諸如key, secret, password, encrypt, API, login, token等關(guān)鍵字來(lái)尋找這些問題。您還可以使用正則表達(dá)式搜索十六進(jìn)制或base64字符串,這取決于您正在尋找的憑據(jù)的密鑰格式。 例如,GitHub訪問令牌是小寫的40個(gè)字符的十六進(jìn)制字符串。像 [a-f0-9]{40} 這樣的搜索模式可以在源代碼中找到它們。這個(gè)搜索模式匹配,只包含數(shù)字和十六進(jìn)制字母a到f的40個(gè)字符長(zhǎng)的字符串。 在搜索時(shí),你可能會(huì)得出像這樣的代碼部分,使用Python編寫:
這個(gè)Python程序從GitHub【2】中獲取用戶名,并打印出用戶的所有存儲(chǔ)庫(kù)的名稱【3】。 這可能是一個(gè)用于監(jiān)視組織資產(chǎn)的內(nèi)部腳本。但是這段代碼包含一個(gè)硬編碼的憑據(jù),因?yàn)殚_發(fā)人員將GitHub訪問令牌硬編碼到源代碼【1】中。 一旦源代碼被泄露,API密鑰就會(huì)成為公共信息。 熵掃描可以幫助你找到不符合特定格式的密鑰。在計(jì)算中,熵是對(duì)某事物的隨機(jī)性和不可預(yù)測(cè)性的衡量。 例如,僅由一個(gè)重復(fù)字符組成的字符串,如aaaaa,具有非常低的熵。一個(gè)更大的字符集的較長(zhǎng)字符串,如wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY,具有更高的熵。 因此,熵是一個(gè)發(fā)現(xiàn)高隨機(jī)性和復(fù)雜性的字符串的好工具,這些字符串通常是一個(gè)密鑰。truffleHog是一個(gè)通過使用正則表達(dá)式和熵掃描來(lái)搜索密鑰的工具。
最后,尋找弱密碼學(xué)算法或哈希算法的使用,這個(gè)問題在黑盒測(cè)試中很難找到,但在檢查源代碼時(shí)很容易發(fā)現(xiàn)。 查找諸如弱加密密鑰、可破解加密算法和弱哈希算法等問題。 grep搜索ECB、MD4和MD5等弱算法的名稱。該應(yīng)用程序可能有以這些算法命名的函數(shù),如 ecb(), create_md4(),或md5_hash()。它也可能有帶有算法名稱的變量,比如ecb_key,等等。 弱哈希算法的影響取決于它們的使用位置。如果它們用于hash對(duì)安全不敏感的值,那么它們的使用將比用于hash密碼時(shí)的影響更小。 新補(bǔ)丁和過時(shí)依賴項(xiàng) 如果您可以訪問源代碼的提交或修改記錄,那么您還可以將注意力集中在最近的代碼修復(fù)和安全補(bǔ)丁上。最近的變化還沒有經(jīng)受時(shí)間的考驗(yàn),而且更有可能包含漏洞,看看已實(shí)現(xiàn)的防御機(jī)制,看看您是否可以繞過它們。 還可以搜索程序的依賴項(xiàng),并檢查它們是否過時(shí)。Grep搜索你使用的代碼語(yǔ)言中的導(dǎo)入函數(shù),搜索關(guān)鍵字如import, require, dependencies。然后看看CVE數(shù)據(jù)庫(kù)中是否有漏洞在他們正在使用的版本上。
掃描一個(gè)應(yīng)用程序的脆弱依賴關(guān)系的過程被稱為軟件組合分析(SCA)。OWASP依賴性檢查工具可以幫助您自動(dòng)化這個(gè)過程。此外,還有具有更多功能的商業(yè)工具。
開發(fā)人員注釋 您還應(yīng)該查找開發(fā)人員的注釋和隱藏的調(diào)試功能,以及意外暴露的配置文件。開發(fā)人員經(jīng)常忘記這些資源,從而使應(yīng)用程序處于危險(xiǎn)狀態(tài)。 開發(fā)人員的注釋可以指出明顯的編程錯(cuò)誤。例如,一些開發(fā)人員喜歡在代碼中添加注釋來(lái)提醒自己未完成的任務(wù)。他們可能會(huì)寫這樣的注釋,從而指出代碼中的漏洞:
您可以通過搜索每種編程語(yǔ)言的注釋字符來(lái)找到開發(fā)人員的注釋。在Python中,它是#。在Java、JavaScript和C++中,它是//。您還可以在源代碼中搜索諸如todo, fix, completed, config, setup, removed等術(shù)語(yǔ)。 調(diào)試功能、配置文件和端點(diǎn) 隱藏的調(diào)試功能通常會(huì)導(dǎo)致特權(quán)升級(jí),因?yàn)樗鼈冎荚谧岄_發(fā)人員自己繞過保護(hù)機(jī)制。 您通??梢栽谔厥獾亩它c(diǎn)上找到它們,因此可以搜索像HTTP, HTTPS, FTP, 和 dev這樣的字符串。例如,您可能會(huì)在代碼中找到一個(gè)像這樣的URL,它指向一個(gè)管理面板:
配置文件允許您獲得有關(guān)目標(biāo)應(yīng)用程序的更多信息,并且可能包含憑據(jù)。 您也可以在源代碼中尋找配置文件的文件路徑。配置文件通常的文件擴(kuò)展名為conf, .env, .cnf, .cfg, .cf, .ini, .sys, .plist.。 接下來(lái),在開發(fā)中查找額外的路徑、棄用的端點(diǎn)和正在開發(fā)的端點(diǎn)。這些都是用戶在正常使用該應(yīng)用程序時(shí)不會(huì)遇到的端點(diǎn)。但是,如果它們能夠工作并被攻擊者發(fā)現(xiàn),它們可能會(huì)導(dǎo)致諸如身份驗(yàn)證繞過和敏感信息泄漏等漏洞,這取決于暴露的端點(diǎn)。 您可以搜索表示URL的字符串和字符,如HTTP、HTTPS、斜杠(/)、URL參數(shù)標(biāo)記(?),文件擴(kuò)展(.php、.html、.js、.json),等等。 詳細(xì)方法 如果您有更多的時(shí)間,用更廣泛的源代碼審查來(lái)補(bǔ)充快速技術(shù),以發(fā)現(xiàn)精妙的漏洞。不要逐行閱讀整個(gè)代碼庫(kù),嘗試這些策略來(lái)最大化您的效率。 重要功能 在閱讀源代碼時(shí),要關(guān)注重要的功能,如身份驗(yàn)證、密碼重置、狀態(tài)更改操作和敏感信息讀取。例如,您需要仔細(xì)看看這個(gè)用Python編寫的登錄函數(shù): sql注入審計(jì)
此函數(shù)通過使用由用戶提供的用戶名和密碼構(gòu)造的SQL查詢來(lái)查找數(shù)據(jù)庫(kù)中的用戶【1】 。 如果存在具有指定用戶名和密碼的用戶,則該函數(shù)將登錄到用戶【2】中。 這段代碼包含了一個(gè)SQL注入漏洞的經(jīng)典示例。在【1】時(shí),應(yīng)用程序使用用戶輸入來(lái)制定SQL查詢,而不以任何方式對(duì)輸入進(jìn)行清洗。 攻擊者可以制定一個(gè)攻擊,例如,通過輸入 admin'-- 作為用戶名登錄作為管理員用戶。這是可行的,因?yàn)椴樵儗⒆兂扇缦聝?nèi)容:
應(yīng)用程序的哪些部分很重要,這取決于結(jié)構(gòu)的優(yōu)先級(jí)。還要研究重要的組件如何與應(yīng)用程序的其他部分進(jìn)行交互,這將向您展示攻擊者的輸入將如何影響應(yīng)用程序的不同部分。 用戶輸入 另一種方法是仔細(xì)閱讀處理用戶輸入的代碼。用戶輸入如HTTP請(qǐng)求參數(shù)、HTTP頭、HTTP請(qǐng)求路徑、數(shù)據(jù)庫(kù)條目、文件讀取和文件上傳,為攻擊者利用應(yīng)用程序的漏洞提供了入口點(diǎn)。這可以幫助找到常見的漏洞,如存儲(chǔ)型XSS、SQL注入和xxe。 聚焦代碼中處理用戶輸入的部分,將為識(shí)別潛在危險(xiǎn)提供一個(gè)良好的起點(diǎn)。還請(qǐng)確保檢查用戶輸入是如何存儲(chǔ)或傳遞的。最后,查看應(yīng)用程序的其他部分是否使用以前處理過的用戶輸入。您可能會(huì)發(fā)現(xiàn),相同的用戶輸入與應(yīng)用程序的不同組件有不同的交互。 url跳轉(zhuǎn)審計(jì) 例如,下面的代碼片段接受用戶輸入。PHP變量$_GET包含URL查詢字符串中提交的參數(shù),因此變量$_GET['next']指的是URL查詢參數(shù)next的值:
此參數(shù)將存儲(chǔ)在$redirect_url變量【1】中。然后,header() PHP函數(shù)將響應(yīng)頭Location設(shè)置為該變量【2】。Location標(biāo)頭控制瀏覽器重定向用戶到哪里。這意味著用戶將被重定向到在URL參數(shù)next中指定的位置。 此代碼片段中的漏洞是開放重定向(url跳轉(zhuǎn)漏洞)。URL查詢參數(shù)next 用于在登錄后重定向用戶,但是應(yīng)用程序在重定向用戶之前不會(huì)驗(yàn)證重定向的URL。它只簡(jiǎn)單的拿URL查詢參數(shù)next的值,并相應(yīng)地設(shè)置響應(yīng)頭。 甚至即使是這個(gè)功能的一個(gè)更健壯的版本也可能包含漏洞。讓我們來(lái)看看這個(gè)代碼片段:
現(xiàn)在,該代碼包含了一些輸入驗(yàn)證: preg_match(模式, 字符串) PHP函數(shù)檢查該字符串是否與正則表達(dá)式模式【1】相匹配。 想必,此模式將確保頁(yè)面重定向到一個(gè)合法的位置。但是這段代碼仍然包含一個(gè)開放的重定向,盡管應(yīng)用程序現(xiàn)在在重定向用戶之前驗(yàn)證重定向URL,但它的驗(yàn)證并不完全。 它只檢查重定向URL是否包含字符串example.com。如在第7章中所討論的。 攻擊者可以通過使用attacker.com/example.com或example.com.attacker.com等重定向URL輕松地繞過這種保護(hù)。 命令注入/xss漏洞審計(jì) 讓我們來(lái)看看另一個(gè)實(shí)例,跟蹤用戶輸入可以給我們指出漏洞。 parse_url(URL,組件) PHP函數(shù)解析URL并返回指定的URL組件。例如,組件為PHP_URL_PATH時(shí),它返回輸入U(xiǎn)RL的文件路徑部分PHP_URL_PATH,此函數(shù)將返回字符串/index.html
您能發(fā)現(xiàn)下面的PHP代碼中的漏洞嗎?
此頁(yè)面包含一個(gè)命令注入漏洞和一個(gè)反射型XSS漏洞。您可以通過注意應(yīng)用程序使用用戶提供的download_file參數(shù)來(lái)找到它們。 假設(shè)這個(gè)代碼所在頁(yè)面url如下:
此代碼檢索URL查詢參數(shù)download_file,并解析URL以檢索其路徑部分【1】。然后,服務(wù)器下載位于example.com服務(wù)器上的文件,文件路徑匹配URL【2】download_file 的文件路徑。 例如,訪問此URL將下載文件https://example.com/abc:
PHP system()函數(shù)執(zhí)行系統(tǒng)命令,system(命令、輸出)將命令的輸出存儲(chǔ)到變量$output中。 該程序?qū)⒂脩糨斎雮鬟f到變量$command,然后傳遞到system()函數(shù)【3】。 這意味著用戶可以將payload注入到$url_path來(lái)執(zhí)行任意代碼。他們只需要在請(qǐng)求頁(yè)面時(shí)干涉GET參數(shù)download_file,像這樣,就能執(zhí)行命令ls:
然后,應(yīng)用程序通過使用直接用戶輸入【4】在網(wǎng)頁(yè)上顯示一條消息。 攻擊者可以在download_file的URL路徑部分嵌入一個(gè)XSS有效負(fù)載,在受害者訪問精心制作的URL后將xss反射到受害者的頁(yè)面上。 URL payload可以使用此代碼片段生成。
練習(xí):審計(jì)漏洞 一些技巧可能看起來(lái)很抽象,所以讓我們來(lái)詳解一個(gè)用Python編寫的示例程序,它將幫助您練習(xí)本章中介紹的技巧。 最重要的是,審查源代碼是一項(xiàng)需要練習(xí)的技能。您越關(guān)注有漏洞的代碼,就越擅長(zhǎng)發(fā)現(xiàn)漏洞。 下面的程序有多個(gè)問題??纯茨隳苷业蕉嗌伲?/p>
讓我們首先考慮一下這個(gè)程序是如何工作的。它使用一個(gè)URL參數(shù)new_password為用戶設(shè)置新密碼。它解析URL參數(shù)中的new_password和csrf_token。然后,它將驗(yàn)證csrf_token,并執(zhí)行POST請(qǐng)求以更改用戶的密碼。 這個(gè)程序有多個(gè)問題。首先,它包含了幾個(gè)有啟發(fā)作用的開發(fā)者注釋【1】。注釋指出,更改用戶密碼是由GET請(qǐng)求發(fā)起的,用戶的新密碼和CSRF令牌都在URL中。在url中傳輸密碼是一種糟糕的做法,因?yàn)槊艽a可能被提供給瀏覽器歷史記錄、瀏覽器擴(kuò)展和流量分析供應(yīng)商,這就產(chǎn)生了攻擊者竊取這些秘密的可能性。 接下來(lái),另一個(gè)開發(fā)者注釋指出,更改新密碼時(shí)不需要用戶的當(dāng)前密碼!第三個(gè)給人啟發(fā)的注釋向攻擊者指出CSRF referer檢查功能未完成【4】。 您可以看到,該程序使用了兩種類型的CSRF保護(hù),兩種都是不完整的。referer檢查函數(shù)僅在referer存在時(shí)進(jìn)行檢查(檢查功能也沒寫),沒有檢查referer是否來(lái)自一個(gè)合法的站點(diǎn)【3】。 接下來(lái),該站點(diǎn)實(shí)現(xiàn)了不完整的CSRF令牌驗(yàn)證。只有csrf_token參數(shù)在URL 【2】中提供它才檢查CSRF令牌是否有效。 攻擊者將能夠通過向用戶提供一個(gè)沒有csrf_token參數(shù)或csrf_token參數(shù)值為空的URL來(lái)執(zhí)行CSRF來(lái)更改用戶的密碼,如下例所示:
代碼審查是發(fā)現(xiàn)漏洞的一種有效方法,因此,如果您可以在黑客攻擊過程中的任何時(shí)候提取源代碼,請(qǐng)深入研究源代碼,看看您能找到什么。 手動(dòng)進(jìn)行代碼審查可能會(huì)耗費(fèi)大量時(shí)間。使用靜態(tài)分析安全測(cè)試(SAST)工具是自動(dòng)化此過程的一種好方法。 存在許多具有不同功能的開源和商業(yè)SAST工具,因此,如果您對(duì)代碼分析和參與許多源代碼程序感興趣,您可能需要考慮使用您喜歡的SAST工具。 該文章在 2024/10/8 20:56:25 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |