Hollow Run Bedding
A small DTC mattress brand co-founded by two cousins in 2019 — two hand-built mattresses, a 100-night trial, and a verified-buyer review thread on each product page where customers post photos of the mattress in their bedroom.
The Scenario
Hollow Run Bedding was founded in 2019 by two cousins in Bird-in-Hand, PA, after a family wedding turned into a long conversation about how every mattress on the market either sagged or smelled. They build two models — a firmer flagship and a softer companion — sell direct, and ship with a 100-night trial. The review thread on each product page fills in steadily; verified buyers post a star rating, a paragraph, and a photo of the mattress in their bedroom. The form was scoped one evening at the kitchen table.
Challenge Intel
Synopsis
The verified-buyer review form on each mattress product page accepts $_FILES['photo'] with no validation at all — no extension check, no MIME sniff, no magic-byte read. Files are stored under /var/www/html/reviews/ which Apache serves directly with its default PHP handler, so an uploaded .php file executes.
What It Is
mattress.php?id=<slug>&action=review accepts a rating, body, and a $_FILES['photo'] upload. The handler does a basename() on the supplied filename (preventing path traversal) but applies no other validation — extension, MIME type, and magic bytes are all unchecked. The file is written to /var/www/html/reviews/<review_id>-<basename>, where <review_id> is the auto-increment row id from SQLite. The review listing renders each review's photo via <img src="/reviews/<id>-<safe>">, leaking the public URL. There is no .htaccess in /var/www/html/reviews/ restricting the PHP handler, so Apache's default config (FilesMatch \.ph(p[3457]?|t|tml|ar)$) executes the uploaded .php file. Player registers, posts a review with a shell.php file containing <?php echo shell_exec($_GET['c']); ?>, observes the public URL, and reads /flag.txt via the resulting RCE.
Who It's For
First-time file-upload exploiters. Assumes the player knows how to register an account and read response HTML. No filter bypasses required — this is the canonical 'no validation' baseline before they meet extension blacklists and magic-byte checks.
Skills You'll Practice
- Identifying an unrestricted upload directory served by an executing handler
- Crafting a minimal PHP webshell and invoking it via GET
- Reading server-side files (/flag.txt) through arbitrary-command execution
What You'll Gain
- Mental model of what an unvalidated upload looks like end-to-end
- Confidence that Apache's default config executes more than just .php
- Baseline for recognising what 'partial mitigations' protect against in later challenges
Ready to hack Hollow Run Bedding?
This challenge is free. Sign up and start hacking.