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