$ cat writeup.md…
$ cat writeup.md…
hackthebox
Task: PHP gallery app with custom C extension (metadata_reader.so) that reads PNG tEXt chunks via strcpy into 56-byte emalloc buffers with no bounds check; LFI in view.php; flag at unknown SHA256-hashed path. Solution: ASLR bypass via /proc/self/maps LFI, heap grooming, Zend MM freelist corruption via strcpy overflow to GOT-overwrite _efree with system(), RCE to list directory, then LFI to read flag.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Dive deep under the web's surface, where 'L' in LFI stands for 'LEAK'. Will you conquer the depths and claim victory?
A PHP gallery web application runs on PHP 8.2.12's built-in development server (single process) with a custom C extension metadata_reader.so that provides a getImgMetadata() function. The extension reads PNG tEXt chunks (Title, Artist, Copyright) and returns them as a formatted string. The flag file is renamed to a SHA256 hash during Docker build, so the filename must be discovered at runtime.
Key files:
index.php — gallery page listing uploads/*.png, calls getImgMetadata() on eachupload.php — uploads PNG files (checks magic bytes + .png extension, no .. in path), calls getImgMetadata() on uploaded fileview.php — LFI via file_get_contents(urldecode($_GET['image'])) — reads arbitrary filesmetadata_reader.so — PHP extension with heap buffer overflow vulnerabilitystart.sh — runs php -S 0.0.0.0:8000 -dextension=./metadata_reader.so in a while true loop (auto-restart on crash)The PHP built-in web server is single-process — all requests are handled sequentially by the same process. This means heap state persists between requests, which is critical for heap grooming and exploitation.
$image = urldecode($_GET['image']); if (file_exists($image)) { echo '<img src="data:image/png;base64,' . base64_encode(file_get_contents($image)) . '">'; }
Double URL-encoding bypasses any path restrictions. Can read any file on the filesystem if the path is known. Used for ASLR bypass (/proc/self/maps) and flag retrieval.
The getImgMetadata() function (at offset 0x1300 in the .so) processes PNG tEXt chunks with a critical flaw:
...
$ grep --similar