你有沒有想過,三個看似零散的技術點——一個數學難題、一個文件讀取技巧、一個編程語言特性——只要按正確順序拼接在一起,就能形成一條直通服務器的攻擊鏈?在TryHackMe的StuxCTF房間里,我們看到的正是這樣一個精巧的串聯案例。整個過程沒有用到任何暴力破解,完全依靠細致的枚舉和線索之間的邏輯關聯,最終實現了遠程代碼執行。下面,我們按時間線的順序,一步步還原這條攻擊路徑。
切入挑戰的第一件事永遠是信息收集。我們啟動了一次常見的端口掃描,工具是Nmap,命令中帶著服務版本探測和操作系統識別的參數。掃描結果很快回顯:22端口運行著OpenSSH 7.2p2版本,80端口則提供著Apache 2.4.18的網頁服務。值得一提的是,Nmap在掃描過程中還自動識別出了網站根目錄下存在一個robots.txt文件,這個文件通常用來告訴搜索引擎哪些路徑不應被索引,卻常常成為偵察階段的第一個信息泄露點。
我們立刻用curl工具獲取了這個文件的內容。返回的結果很簡潔,只有三行注釋和一條規則。注釋里寫道“robots.txt generated by StuxCTF”以及一個醒目的關鍵詞“Diffie-Hellman”;規則部分則明確地將一個路徑“/StuxCTF/”列入了禁止訪問列表。短短幾行內容,一下子拋出了兩條重要線索:一個隱藏目錄路徑,以及一種名為Diffie-Hellman的密鑰交換算法。在CTF挑戰里,“禁止訪問”往往意味著“你應該去看看”,于是我們立刻把注意力轉向了這個目錄。
訪問/StuxCTF/并沒有返回任何直觀的內容,但它主頁的HTML源代碼里卻藏著一個巨大的提示。我們在源代碼中看到一段被注釋掉的文本,里面包含了四個關鍵參數:一個非常大的質數p,一個生成元g(數值為7),兩個私有指數a(330)和b(450),以及一個以g^c表示的公鑰數值。這明顯是一個Diffie-Hellman密鑰交換的參數組,但它比常見的兩方交換多出了一個c,暗示這里存在第三方。
如果對Diffie-Hellman算法的原理稍作回顧,就不難理解這些參數的含義。標準的Diffie-Hellman讓通信雙方在公開信道上協商出一個共享秘密,而不直接傳輸秘密本身。基本過程是:雙方約定一個大質數p和生成元g;各自選擇私有指數(比如a和b),分別計算出對應的公鑰(g^a mod p和g^b mod p)并交換;然后雙方用對方的公鑰和自己的私有指數再次進行模冪運算,得到相同的共享秘密。在這個挑戰里,我們看到了兩個私有指數a和b,說明這兩個值可能屬于兩個已知的參與方;而那個g^c則是第三個參與方的公鑰,我們不知道它的私有指數c,但卻擁有它的公鑰。
因此,這個場景被設計成一個三方的Diffie-Hellman結構:參與方A的私鑰是a,參與方B的私鑰是b,我們不知道C的私鑰,但持有C的公鑰g^c。想要計算出最終的共享秘密,我們需要依次進行模冪運算。具體做法是:先用g^c作為底數,以a為指數,模p計算出(g^c)^a mod p的值;然后再以這個結果作為底數,以b為指數,再次模p,得到((g^c)^a)^b mod p。由于模冪運算在正整數上的交換性質,這個最終結果等價于g^(a*b*c) mod p,是三方共享的秘密。當然,我們并沒有去探究為什么會有三方,挑戰的意圖顯然是讓我們算出這個秘密數值,然后把它用作下一步的線索。
計算過程很簡單,寫一個Python腳本就能搞定。我們把注釋中提取的p、g^c、a、b代入,利用內置的pow函數一步完成模冪——Python的pow函數支持第三個參數作為模數,既高效又準確。運行腳本后,控制臺輸出了一長串數字,我們只取其前128位(代碼里已經做了截斷),這串數字就是我們要找的隱藏目錄名。緊接著,我們在瀏覽器地址欄后面拼上這串數字,一個原本不被發現的目錄就呈現在了眼前。
進入這個隱藏目錄后,看到的頁面極為簡單。標題寫著“Follow the white rabbit..”,好像又在暗示我們繼續深入。頁面中只有一個指向index.php的超鏈接,但這段HTML的源代碼里卻給了一個很短的提示:一個注釋中出現了“hint: /?file=”,這個格式直接讓人聯想到本地文件包含漏洞的典型參數傳遞方式。
本地文件包含,通常簡稱為LFI,是Web應用中一種常見的漏洞類型。當應用程序接收用戶傳入的文件路徑參數,并直接包含該文件到頁面中執行時,如果缺少充分的過濾和校驗,攻擊者就能夠讀取服務器上的任意文件。這個提示里的“/?file=”結構,通常意味著我們可以通過GET參數指定一個文件名,應用程序會去包含并執行它。于是我們嘗試利用這一線索,讀取index.php自身的源代碼,使用的payload形如:?file=php://filter/convert.base64-encode/resource=index.php。通過php://filter封裝器,我們可以讓PHP以base64編碼的方式返回文件內容,從而避免直接執行腳本,完整地把源碼看清楚。
解碼后,我們獲得了index.php的全部邏輯。其中最關鍵的一段代碼判斷了是否存在一個名為“file”的GET參數,如果存在且文件存在,則直接include該文件。更為致命的是,在同一個文件中,我們還發現了一個類定義,該類實現了PHP的魔術方法__destruct(),并在析構時會執行一個系統命令。命令的參數取自對象的某個屬性,沒有任何過濾。這意味著,如果我們能控制傳入unserialize()的數據,就可以在對象被銷毀時觸發任意命令執行——這正是PHP反序列化漏洞的經典利用模式。
接下來的攻擊路徑就變得清晰了。我們構造一個惡意序列化對象,讓它的命令屬性包含我們想要執行的系統指令,例如一個反向shell或者直接讀取flag文件的命令。然后通過LFI包含一個我們可以控制的臨時文件,或者更直接地,利用某些場景下參數本身就可能被unserialize的情況。在這個挑戰中,進一步的偵察讓我們發現,index.php在接受file參數的同時,還會從另一個參數中獲取數據并進行反序列化。我們將構造好的Payload通過這個參數傳入,服務器在腳本結束、對象銷毀的時刻,自動觸發了__destruct(),執行了我們注入的命令。
最終,整個攻擊鏈完成:通過Diffie-Hellman的三方計算揭開隱藏目錄,再用LFI讀取源碼,找到反序列化入口,最后通過精心構造的PHP對象實現遠程代碼執行。全程沒有使用任何爆破手段,每一個步驟都依賴于對前一步線索的準確解讀。這個挑戰恰好說明了一件事:現實中,致命的漏洞往往不是孤立存在的,而是多個看似不起眼的小問題被依次打通后形成的完整通道。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.