WEBVERSE

Loading...

Inked
mediumFree

Inked

Jill's Tatt Shop is a custom tattoo studio with a public booking site, an internal admin CRM the artists use to triage appointment requests, and a customer API behind it. Booking requests flow from the public site into the staff dashboard — start as an anonymous visitor and see how far into the back office you can get.

host-header-injectionpassword-reset-poisoningout-of-bandsstitwigjwtrcephpmysql
phpapachetwigmysqlnginxpython

The Scenario

Jill's Tatt Shop books fast and runs lean: a slick public site where clients

request appointments, a staff dashboard where the artists triage those

requests, and a CRM API tying it together. After a client's contact details

turned up somewhere they shouldn't have, Jill brought you in to test the shop's

systems end to end.

You start on the public site as an anonymous visitor. The staff dashboard lives

on its own subdomain and only shows a login. Your objective: get into the staff

back office, find your way to whatever it's talking to, and read what the studio

is hiding on the box.

Lab Intel

Synopsis

Jill's Tatt Shop spans a public booking site, an admin CRM dashboard, and a docs-off CRM API. A host-header-injection password reset (delivered out-of-band by a mail bot) yields admin access; the dashboard then reveals a CRM API whose appointment-preview endpoint renders the client's message through Twig — a server-side template injection that escalates to RCE and reads the flag.

Architecture

A medium-difficulty six-container lab (nginx gateway, three PHP/Apache surfaces, a Python mail bot, MySQL). Vuln 1: admin POST /forgot-password builds the reset link from the X-Forwarded-Host header and stores it; a bot 'reads the email' by visiting that link, so poisoning the header to your VPN-IP listener leaks the admin's reset token out-of-band. Vuln 2: the public booking form is forwarded server-side to crmapi (so crmapi stays hidden), and crmapi's GET /appointments/:id renders the booking message through Twig's createTemplate() with the sandbox off — a Twig SSTI. The two are gated: crmapi's endpoints and JWT are only discoverable from the dashboard's client-side XHR after the admin takeover. The same HS256 JWT authenticates to both admin and crmapi (no audience check). RCE runs as the 'virgal' user; the flag is at /home/virgal/flag.txt.

Who It's For

Built for intermediate testers comfortable chaining an out-of-band web vuln with backend exploitation. You should understand HTTP headers behind reverse proxies, how to run a listener over the VPN, JWT bearer auth, and Twig/SSTI template-injection-to-RCE primitives.

Skills You'll Practice

  • Host-header / X-Forwarded-Host injection in password-reset flows
  • Out-of-band token capture via a bot + attacker-controlled listener
  • Reverse-proxy + subdomain reconnaissance and JWT bearer reuse across services
  • Server-side template injection in Twig (PHP)
  • Twig SSTI to command execution with the callback-filter primitive

What You'll Gain

  • Why reverse proxies must never let a client-supplied host header reach link-building code
  • How out-of-band delivery turns an otherwise-blind reset poisoning into account takeover
  • Recognising a docs-off API by watching a SPA's client-side calls, and reusing its bearer token
  • Turning a Twig template-injection sink into reliable RCE without a planted filter

Ready to hack Inked?

This lab is free. Sign up and start hacking.