超越OSCP:Exploit 除錯之術

在滲透測試、打靶機、CTF中,我們經常會遇到 exploit 無法順利執行的情況。有些問題很好解決,但有些則需要更多技巧與耐心來除錯。本文將分享一些在除錯 exploit 時的關鍵思路與技巧,讓你在遇到障礙時能更快找到解決方法。希望這篇文章可以給所有準備實戰考試或是滲透與紅隊的新人來帶來幫助。

前言:確保工具、了解工具、熟悉工具

古語有云:「工欲善其事,必先利其器」。

在執行滲透測試與任何實作考試前,確認你的每一個工具、腳本可以正常運作,是非常重要的事情。而且這將花費大量的時間,卻幾乎是無可避免的。而對於考試而言,隨著時間的變化,工具和腳本的變動可能越來越多,因此不建議將準備時間拉得太長。例如,如果你計畫準備一年,你 1 月份所使用的工具與腳本,到了 12 月可能就無法正常運作。

確保工具可用之後,第二步則是了解工具,這個過程肯定也會花費大量的時間,但相較於準備與確保工具階段屬於安裝與除錯的費時。在了解工具階段會更側重於對於技術原理的了解,以及對工具運作方式的了解。

最後可能要熟悉工具,這個階段包含了解不同場景所適合使用的工具,以及工具的參數熟悉度。但由於工具實在太多,也不太可能全部了解,可以針對幾個你覺得習慣使用或重要的工具進行深入學習。這個環節硬要說可以算最不重要的,因為熟悉只是幫助效率加速,如果第一跟第二階段的工具運作正常,也了解該工具用途,再慢慢看官方手冊或是網路搜尋如何使用參數也不太遲。

主題:關於Exploit

雖然從工具起頭,但我好像有點離題了,這篇文章畢竟是要講Exploit。除了一些常見通用的工具與腳本外,我們在滲透測試或技術認證的實戰考試中,也可能會需要使用到一些 exploit,也應該了解其運作方式。這樣可以避免腳本本身是正常的(或是稍做調整即可用),但因為你不了解其內部邏輯,導致錯誤判斷。例如,某些 exploit 可能要求特定條件,若未滿足就無法成功利用。

比起一般常見的通用型駭客工具,例如smbmap、ldapsearch、hydra等等。我們通常無法於事先準備好exploit的可用性與穩定性,畢竟網路上實在是有太多的POC與Exploit。所以很仰賴於我們在當下對於該漏洞與exploit的了解,以及有足夠的技術知識能夠去正確的使用它或是修復它(指的是修復腳本,不是修復漏洞)。

實際上若有上過OSCP課程的人,也明白課程當中有一個章節(Fixing Exploits)是專門在介紹與教學如何正確使用Exploit,還有如果Exploit有問題要如何除錯。今天這篇文章的內容可能沒有比OSCP課程內容的該章節內容長度多,但相信對於Exploit除錯的提醒是更加豐富的。

也希望各位精進滲透測試,或是準備各項實戰考試,不僅僅是OSCP,或是CEPNT、PNPT、HTB CPTS時,這篇文章內容都可以帶給大家莫大的幫助。

Exploit 除錯之術

雖然Exploit可能不僅僅是一個「腳本」或「程式」,有時候是一連串的步驟與說明,但這邊的文章比較側重在於腳本的exploit。

當Exploit不能使用時,不要急著放棄。首先當然是耐心查看畫面顯示的錯誤,仔細查看錯誤訊息,分析訊息來排除問題。而對於各種常見Exploit失敗的可能原因,可以從以下幾個角度切入:

  • 了解漏洞利用條件
  • 了解腳本使用方式
  • 檢查是否缺少依賴
  • 入口點/注入點錯誤
  • 查看 exploit 是否寫死了某些變數(Port、路徑、帳密等)
  • 是否有需要身分驗證或密碼
  • 執行方式錯誤
  • 確認是否需要編譯,並尋找可行的編譯環境
  • 繞過不必要的版本檢查機制
  • 確保 exploit 的檔案操作不會受到環境影響
  • 退而求其次,轉換使用方法

以下會針對每一個項目進行解說。

了解漏洞利用條件

第一個很基本,但還是要說。為什麼你會選擇使用這個exploit?是因為看到有這個服務,還是隨便 google 找一個關鍵字就看到這個exploit?你有確定目標服務版本與設定是有符合這個漏洞的嗎?

雖然使用錯誤的exploit,打了也不會怎麼樣,但可能會很浪費時間。所以使用exploit前還是稍微花費短短的時間了解一下漏洞影響範圍、以及漏洞的利用條件。

例如也算有名的Spring4shell高風險安全漏洞(CVE-2022-22965),其實也不是看到Spring Framework就隨便打就隨便成功的,它的符合條件也不少。必須是:

1.使用Spring Framework 5.3.0~5.3.17、5.2.0~5.2.19或更舊之版本
2.使用JDK 9(含)以上版本
3.使用Apache Tomcat做為Servlet容器
4.網站專案使用Java web archive(WAR)方式封裝,並部署於獨立之Tomcat實體
5.Tomcat具有spring-webmvc或spring-webflux相依性

Spring4shell高風險安全漏洞參考來源:

https://www.nics.nat.gov.tw/core_business/information_security_information_sharing/Vulnerability_Alert_Announcements/1208

了解腳本使用方式

不管是在Exploit-DB或是Github上面找到的exploit,通常都會有個使用說明,或是寫在腳本的開頭註解當中。好一點的話也可以使用參數-h查看使用說明。了解使用方式以及參數用途,畢竟每個撰寫exploit的人想法可能不同,有時候也會有細微的差異。

如果exploit釋出的地方有提供example的話,當然是最好~但有時候可能需要自己摸索嘗試一下。例如參數的順序,是否要加上引號,引號是否會有差異等等。

例如以下四個指令,乍看之下好像都是一樣的,但實際上對於exploit.py這支程式來說是不是一樣的可就不一定了。

./exploit.py -u 'test' -p 'password' --file /etc/passwd
./exploit.py -u 'test' -p 'password' --file '/etc/passwd'
./exploit.py -u "test" -p "password" --file "/etc/passwd"
./exploit.py --file "/etc/passwd" -u "test" -p "password" Code language: JavaScript (javascript)

入口點/注入點錯誤

新手入門第一個常見錯誤!就是入口點跟注入點就錯了。

有些題目只是稍微變化一下Port或是URL路徑,你如果照著原本example的輸入就會失敗了。

所以要再三確認一下:

  • 是否有選擇正確的Port或路徑?
  • 該exploit使用的是否為HTTP還是HTTPS?
  • 如果是HTTPS,是否需要忽略自簽憑證憑證?
  • 使用的方法為GET還是POST?
  • 注入點的參數名稱是不是正確的?

例如我們看到CVE-2023-32315這個Exploit的使用方法,是帶上完整的URL,如果你的目標服務不是開啟在9090 Port,但你學畫面上的用法輸入http://192.168.xx.xx:9090,那當然怎麼打都打不動。

https://github.com/K3ysTr0K3R/CVE-2023-32315-EXPLOIT

那這邊雖然以WEB為例去說明,但對於其他網路協定或是本地漏洞也是要注意注入點的問題。

檢查是否缺少依賴

這可能也是最常見的問題之一,但通常畫面上會顯示明確的錯誤,所以應該不太困擾。(困擾的是後續安裝的過程XD)

以常見的python撰寫的exploit,缺少 Python 的 pip 套件,如果exploit專案中requirements.txt有,可執行 pip install -r requirements.txt 即可解決。如果沒有的話requirements.txt,可以查看執行後顯示缺少甚麼依賴項,直接透過pip進行安裝。

若需要其他工具輔助,例如 socatgccnc 等,這些可能需要在攻擊機或目標機上安裝或下載。

執行方式錯誤

執行方式錯誤,也是初學者偶爾會發生的奇妙錯誤。

有些 exploit 是用 Python 撰寫的,但不同版本的 Python 可能導致執行錯誤。例如:

python exploit.py # 可能報錯
python2 exploit.py # 嘗試用 Python 2 執行
python3 exploit.py # 嘗試用 Python 3 執行Code language: CSS (css)

如果遇到 SyntaxErrorModuleNotFoundError,嘗試不同版本的 Python 來執行,或直接查看腳本的 shebang (也就是開頭的#!)行來確認相容性。

除了python以外,也有很多exploit是利用其他開發語言撰寫的,或是shell script。如果連執行方式都不正確,程式跑不起來,Exploit也無法成功。

是否需要編譯

若對於開發語言或是程式設計比較有經驗的,可能比較不會遇到這個問題。某些 exploit 需要事先編譯,這時候要確認幾件事:

  • 編譯需要的工具是否齊全,例如 gccclangmake 等。
  • 是否可以在攻擊機先編譯好,再傳到目標機。
  • 目標機是否允許編譯(例如某些受限環境可能沒有 gcc)。
  • 有沒有替代方案,例如 musl-gccstatic binary,甚至是手動編譯 C 原始碼。

若無法在目標機編譯,可以考慮在本地編譯後傳過去(但要考量環境因素),或使用交叉編譯方式來生成對應的二進制。

查看 exploit 是否寫死了某些變數(Port、路徑、帳密等)

這部分與前面了解腳本使用方式以及入口點有點點類似。但這邊更強調的是,使用上有可能較少會去變動到的地方,所以撰寫Exploit的人將它給寫死(Hardcode)在程式碼當中。這樣的情況有時候使用者不會在第一時間注意到。

這部分老實說也不算進階,但相對起來,這個環節可能是滲透測試考試的話,比較有可能考的東西吧?(畢竟再簡單就太簡單,再難又太難)

有些 exploit 可能會將攻擊目標的 port 寫死,導致無法適應不同環境。例如:

TARGET_PORT = 8080 # 可能需要改為 80Code language: PHP (php)

遇到這種情況,可以直接修改腳本內的參數,讓它適應你的目標環境。

除了 port,某些 exploit 也可能會寫死目標的路徑,例如:

url = "<http://target.com/admin/login.php>"
Code language: HTML, XML (xml)

如果目標環境不同,可能需要手動調整 URL、API Endpoint 或 Payload 中的路徑。

以路徑來說,在某些漏洞或是目標中是比較有挑戰性的。可能會仰賴於你對於漏洞有足夠正確的認識,以及可能是組合式的攻擊方式。

過往曾經有一題靶機,漏洞利用當中的路徑是寫死一個目標主機上的絕對路徑,但該路徑其實是錯誤的。是透過另一個漏洞有發現目標主機的絕對路徑洩漏,所以才回頭改exploit當中的絕對路徑,才能夠成功利用。

通常大概就是Port、路徑、檔案名稱、參數名稱之類的修改調整,不會有去改IP的。但有一種情況基本上一定要改IP,就是exploit是要取得reverse shell。

以CVE-2022-35525這個exploit來看,一個常見的情況,就是有reverse shell的exploit,會需要去寫入你的IP與Port。如果你的exploit是屬於reverse shell類型,但沒有參數或是程式碼要你修改IP跟Port,你應該就要察覺是不是哪裡不對勁了。

  $ip = '192.168.228.128';  // You have changed this
  $port = 1337;  // And thisCode language: PHP (php)

https://github.com/0xk4b1r/CVE-2022-3552/blob/main/CVE-2022-3552.py

是否有需要身分驗證或密碼

某些 exploit 需要帳號密碼、Session、API Key 或 Token,這些通常會有預設值,例如:

default_user = "admin"
default_pass = "password"Code language: JavaScript (javascript)

如果 exploit 內建的憑證無法使用,記得檢查是否可以手動輸入正確的帳密。

這一項也如同前一點,許多的Exploit可能會有預先寫死的帳號與密碼。但你的目標系統或服務可能是使用其他你所列舉找到的帳號密碼,就要自行去替換。

除了常見的設定帳號或是密碼之外,也要注意有些是Key或是Token的。

例如 Metabase Pre-Auth RCE (CVE-2023-38646) POC

https://github.com/m3m0o/metabase-pre-auth-rce-poc

看使用以及參數說明,就會發現有個參數 -t 是需要帶上 token 才可以成功利用的。

會特別把這一點強調出來,也是許多新手在搜尋與利用Exploit時,經常會忘了先留意這個Exploit是否有需要身分驗證或是授權的條件。

版本檢查機制

有些 exploit 會先檢查目標的版本,例如:

if banner != "Apache/2.4.49":
    print("Target not vulnerable!")
    exit()Code language: PHP (php)

這樣的機制實際上可能是出於好意,多加一層檢查機制來做一個POC檢查,避免浪費時間。但有時候這種檢查機制可能會被錯誤的 Banner 影響(或是Banner其實被移除,但漏洞還在),導致 exploit 無法執行成功。我們可以透過註解掉這段程式碼,或強制修改回傳值來繞過這類機制。

無法寫入/覆寫的檔案

這一點與前面所提及的寫死的路徑與檔案稍有不同。

這邊更強調的是有些路徑或檔案,由於權限或是已經存在的緣故,導致無法正常執行Exploit。

有些 exploit 會在目標機器上寫入特定檔案,例如:

/tmp/exploit_payload

如果目標機上已經有這個檔案,而且我們無法覆寫,就需要修改 exploit 的寫入路徑。例如:

payload_path = "/var/tmp/mypayload"Code language: JavaScript (javascript)

換一個目錄路徑可能就能解決問題。

例如我當初在HTB一台靶機上面要執行一個exploit也一直失敗,後面發現是我要做DLL Hijacking的時候,不知道為什麼已經有一個dll檔案在那邊但我無法覆寫它,導致我產生dll檔案一直失敗。後來用以下的指令把那個dll檔案給改名,再次執行就成功了。

Rename-Item -Path "upload.dll" -NewName "test.txtCode language: CSS (css)

關於這一項,其實也是要仔細看看腳本當中建立的檔名跟路徑是否有意義的。有些情況下,把這些名稱改掉也沒問題,尤其是許多的exploit目的可能是上傳或注入一個Webshell。

漏洞是否只能利用一次

這個其實算是歸類在第一項的「了解漏洞利用條件」當中,但因為不管在實務滲透測試或是考試當中,都有其重要性,所以特別要說明一下。

甚麼叫做漏洞只能利用一次呢?就是字面上的意思XDDDD

有些漏洞可能只能打一次(不論成功或失敗),後面第二次你就一定只會失敗,必須要重啟服務才能夠再進行漏洞利用。也有一些漏洞屬於第一次成功之後,第二次以後就一定都會失敗的。

檢查環境變數影響

某些 exploit 可能依賴 LD_PRELOADPYTHONPATH 這類環境變數,確保變數正確設定。

如果有發現調用的變數或是程式碼裡面有用到環境變數,可以用env確認看看。

不排除這種可能,但我自己實務上沒有遇過。

考慮目標系統的防禦機制

這一項是比較進階的考量,如果不是參與需要防禦繞過的考試,或是實戰的滲透與紅隊演練,通常的考試應該是不需要考慮此項。

目標主機上可能會有WAF、SELinux、AppArmor、ASLR、DEP 這類安全機制可能影響 exploit 成功率,必要時需找繞過方法。

確認網路與防火牆影響

某些 exploit 需要開放特定 port,若被防火牆擋住,可使用 socatchisel 建立反向 Shell 通道。

而關於更多與防火牆或是Reverse shell的相關除錯,我們則會於下一篇文章去詳細探討

退而求其次,轉換手動利用

最後一招,可能不算是正解。但也是一個解決方法,同時也是我其實滿常使用的方法。

也就是當Exploit真的無法成功執行時,我會去查看Payload的內容,然後嘗試看看能不能直接透過手動的方式來去漏洞該漏洞。畢竟重點是在於漏洞利用,如果exploit裡面的內容都看懂了,就也不需要強求一定要讓腳本能夠成功執行。如果是常見的漏洞類型,例如LFI、SQL Injection、File Upload等等,看懂腳本裡面的注入點以及Payload,就乾脆直接用Burp Suite來使用就好了。如果是一些網路協定的Exploit,不太複雜的情況,也是可以使用necat或是python來達成就好。

一個Exploit的範例:DirtyPipe

DirtyPipe 是一個經典的例子。它是一個知名且相對常見的權限提升漏洞 exploit。雖然使用上很簡單,但如果沒有正確了解用法的話,其實也是沒辦法無腦成功利用的。

在這個 exploit 中,它使用 gcc 編譯,並將可執行檔案放在 /tmp 目錄內。但事實上,這個 gcc/tmp 目錄的名稱是可以更換的,並不影響 exploit 的運作。

同時,DirtyPipe 利用的條件包含系統上需要有一個 SUID 檔案,這個 SUID 檔案可以是任何 SUID,不一定要是特定的檔案。因此,在理解 exploit 時,應該弄清楚這些細節,避免因為預設值與目標環境不同而導致失敗。

最後提醒

exploit 修補與除錯這件事情,很多時候是跟『自身的環境』(例如我們通常使用的可能是Kali Linux)與『目標主機與服務』有關聯。所以並不是說,可以先下載好一個Exploit之後,把它修改運作到好之後,之後就可以順利在任何場景使用的。也因為Exloit的使用很依賴於環境與目標,所以Fixing Exploits,是需要多花一些時間打靶機練習,也時常補足自己的一些技術知識的才行。

發佈留言