neven@dimitri-dev:~$
cd ../hacknite-2021

$cat authentication.mdWebHacknite 2.0

Authentication

A cookie holds a packed-up object that tells the server which file to read. Rebuild it to point at the flag file and the server hands it over.

  • #deserialization
  • #php-object-injection
  • #base64
  • #cookies

$man authentication

What this one teaches:

  • What base64 is, and how to read a cookie that's been encoded with it.
  • What serialising an object means (packing it into text and rebuilding it later).
  • PHP object injection, where a tampered cookie makes the server rebuild an object you control.

$hint --one-at-a-time

Stuck? Open one hint, then go back and try again before reading the next.

Hint 1 of 2show

The interesting cookie is base64. Decode it and see what it describes.

Hint 2 of 2show

You have the source. What does the server do with the object it rebuilds from the cookie?

Full solution below. Spoilers ahead.

Task description

While researching online, Ana found a novel way to log in as admin with no username or password. Pleased with it, she saved something interesting at /usr/local/flag.txt, but to read it you have to be signed in as admin.

The original was in Croatian; this is my translation.

Like Hidden Admin Content, this turns on a cookie. In the developer tools (Inspect, then Application or Storage) there’s a cookie named message with a long scrambled value.

That value is base64. Base64 is a way of writing any data using only plain letters and digits, so it can travel safely in places like cookies. It isn’t encryption; anyone can decode it. Pasting it into a base64 decoder showed it wasn’t a word but a packed-up object.

The task gives us the site’s source. In evenmoresecure.php, the key line is:

<p><?php print(unserialize(base64_decode($_COOKIE["message"]))->get_file()); ?></p>

Reading it from the inside out: take the message cookie, base64-decode it, then unserialize it. Serialising means packing an object (a bundle of data and the actions that go with it) into a line of text so it can be stored; unserialising rebuilds the object from that text. The rebuilt object here is a FileAccess with a filename, and the page calls its get_file(), which reads and prints that file.

The decoded cookie showed the filename set to /usr/local/default.txt. Since the server rebuilds the object straight from the cookie, we control the filename. This is PHP object injection: the server trusts a serialised object that the visitor can swap out.

Pointing it at the flag

We built the same object with the filename changed to the flag, then serialised and base64-encoded it, using a free online PHP sandbox:

<?php
class FileAccess {
    private $filename;
    function set_filename($f) { $this->filename = $f; }
    function get_file() { return file_get_contents($this->filename); }
}
$a = new FileAccess();
$a->set_filename("/usr/local/flag.txt");
print(base64_encode(serialize($a)));

We pasted its output over the message cookie, reloaded, and the page read /usr/local/flag.txt and printed the flag.

The fix is to never rebuild objects from data the visitor controls. Keep the state on the server and give the cookie only a random session id.

$cat flag.txt revealCTF2021[254352283512]

Written by Neven Marić. This writeup was written with the help of Claude Code (Anthropic).