Asad

ASAD

ASAD

Insecure Deserialization – Portswigger Lab 2: Modifying serialized data types

Introduction

Insecure deserialization vulnerabilities can often open the door to critical exploits, especially when combined with quirks in language-specific behaviors. In this blog, we’ll walk through a real-world-style lab from PortSwigger that demonstrates how PHP’s type juggling—specifically in versions 7.x and earlier—can be abused to escalate privileges. By carefully modifying a serialized object in a session cookie, we’ll gain administrative access and complete the challenge step by step.

Understanding PHP Type Juggling in Serialized Objects

In addition to modifying attribute values in serialized objects, attackers can also manipulate the data types themselves. PHP’s loose comparison (==) makes it especially vulnerable in such cases.

For example, in PHP 7.x and earlier, when comparing an integer with a string, PHP attempts to convert the string to an integer. So expressions like 5 == "5" and even 5 == "5 of anything" return true. This is because PHP only evaluates the initial numeric portion of the string.

Even more critical, 0 == "example string" also evaluates to true because PHP treats the entire string as the integer 0. This becomes a serious issue when such comparisons are used in authentication logic.

Take this pseudocode:

php
CopyEdit
$login = unserialize($_COOKIE);
if ($login['password'] == $password) {
    // Successful login
}

If an attacker sets the password value in the serialized cookie to an integer 0 instead of a string, and the actual stored password does not start with a number, the condition will still return true, leading to an authentication bypass.

⚠️ This is possible only because deserialization preserves data types. If the value was passed directly in a request (e.g., as a string), this type juggling would not work.

🔐 Note: PHP 8 changed this behavior — 0 == “example” now returns false. However, type juggling with strings starting with numbers (like 5 == “5abc”) still works the same way.

💡 Always remember: when altering serialized objects, you must adjust both the value and its type label/length in the serialized string. Failing to do so will result in a corrupted object and failed deserialization.

Walkthrough

We’re going to solve this PortSwigger lab by analyzing and exploiting a vulnerability in its web application.

 

Step 1: We begin by logging in with the credentials wiener:peter and capturing the HTTP traffic in Burp Suite. This helps us analyze the request and response patterns of the web application.

 

Step 2: In Burp Suite, we observe the login request and its corresponding response. Within the response, we identify the session cookie. Our next step is to analyze this cookie to check if it contains any serialized data.

 

Step 3: After capturing the login request in Burp Suite, we examined the session cookie and decoded it from Base64. The decoded content revealed a PHP serialized object:

Original Cookie: Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJ3ZWw4Y3AxZm5nMTB0ZjJ6N3duankxMnR0ejN5MjJ5dyI7fQ%3d%3d

Decoded Cookie:O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"wel8cp1fng10tf2z7wnjy12ttz3y22yw";}

This serialized object shows a User class with two attributes:

  • username: “wiener”
  • access_token: “wel8cp1fng10tf2z7wnjy12ttz3y22yw”

This confirmed that the application uses serialized data to manage user sessions, which opens the door to potential manipulation.

 

Step 4: Now, we exploit PHP’s loose comparison behavior by changing the data type of the access_token from a string to an integer.

Modified Cookie: O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";i:0;}

After making this change, we encode the modified serialized object back into Base64 to use it as the new session cookie.

 

Step 5: To apply the changes, use a cookie editor extension or browser inspection tools to replace the current session cookie with the one you’ve crafted. After updating the cookie, refresh the page to observe the updated session behavior and confirm the changes are reflected.

 

Step 6: Now that we can see the Admin panel after replacing the session cookie and refreshing the page, the next step is to navigate through the Admin panel to view the user list.

 

Step 7: We can see two users, “wiener” and “carlos,” in the Admin panel. According to the lab instructions, we need to delete the “carlos” user to solve the lab.

Step 8: Once the “carlos” user is deleted, the lab is considered solved, and a pop-up message will appear saying, “Congratulations, you solved the lab!”

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top