Libwary
This was an interesting PHP challenge showcasing the potential impacts of insecure deserialization.
Description
Try to read the flag from The Libwary. (Impossible)
The source code for this challenge can be found here.
Spotting the Vulnerability
When looking at index.php
, we see that our user
object is deserialized
from the PHPSESSID
cookie. Deserializing user input is always a huge no-no,
as users can send specially crafted payload to pwn the server.
In this case, the User
class is being serialized, converted to base64,
and saved to the PHPSESSID
cookie. The server will then deserialize it
when the user makes the request again.
What is Serialization and Deserialization?
When we create objects (or classes) during a program’s runtime, it is represented as binary directly inside the program’s memory. Once the program ends, the object ceases to exist. Some programs require the state of the objects to be preserved even after the program ends. This is where serialization and deserialization comes in handy. It allows objects to be saved in a structured format on our hard disks.
For example, we have a book object in Python, and we would like to save it:
A serializer could convert this into JSON (or any other format) and save it like this:
This is a rather simple way to serialize and lacks a decent number of features, such as saving functions and custom data types. If you’d like to find out more, Python has an amazing library for serialization and deserialization called pickle, and this guide explains how to use it.
Serialization & Deserialization in PHP
PHP stores the objects in a JSON-like format like {type:length:value}
.
Do refer to the PHP serialization documentation
for a more detailed explanation.
Exploiting this Vulnerability
So how can we use this to our advantage? In the image above, we see that we have
control over the object
property. Thus, we can modify this to be a Book
instead
of a User
, with a property name
containing flag.txt
!
However, there’s a catch. We see that in the __tostring
function of Book
, there
is a filter that replaces flag
with an empty string. Thankfully, there’s a trivial way to
overcome this filter by using the payload flflagag.txt
. Since this function
is not recursive, it only removes a single occurrence of flag
. We can wrap this within
another flag
string, and after it runs through the filter, we would be left with flag.txt
!
We can modify the cookie to be a Book
with name flflagaag.txt
using
this command, and setting it with inspect element: