TwinTone
TwinTone Books is a bookkeeping app for a small business. You have a guest login (guest / guest) that is only meant to reach the overview dashboard. Find out how much further that guest account can actually get.
The Scenario
TwinTone Books keeps the accounts for a small studio. During a review, a guest login that is only supposed to see the overview dashboard was found reaching parts of the app it was never granted, and touching records it should not have been able to see.
You have the same guest login. Sign in as guest and work out how far that account can really get inside TwinTone Books.
Lab Intel
Synopsis
TwinTone Books is a Ruby / Sinatra bookkeeping app. The guest account (guest / guest) can only reach the dashboard and settings, enforced server-side. The settings update handler merges every posted field that matches a real users column with no allowlist, so over-posting role=admin promotes the guest. As admin the expense reports feature is reachable, and an expense report's title is folded into an ERB template string and evaluated, giving ERB SSTI and RCE. The flag at /flag.txt is read after code execution.
Architecture
A medium two-container lab (nginx gateway + a Ruby 3.2 / Sinatra app with embedded SQLite). The headline vulnerability is ERB server-side template injection on the first Ruby stack in the catalog. Chain: (1) sign in as guest; the sidebar shows every feature but the admin ones are locked and 403 server-side. (2) The POST /settings profile update has no strong-parameter allowlist, so adding role=admin escalates the guest to admin. (3) As admin, GET /expense-reports/:id builds a branded heading with ERB.new("...#{report.title}...").result(binding), so a report titled with an ERB tag such as <%= `cat /flag.txt` %> executes. Every other title render uses HTML escaping and is inert, so the show-page heading is the only SSTI sink and the settings mass-assignment is the only privilege escalation.
Who It's For
Testers comfortable with authenticated web apps who want a clean two-step chain: a mass-assignment privilege escalation into an ERB template-injection RCE. Some familiarity with reading a request in a proxy and with template-injection payloads helps.
Skills You'll Practice
- Spotting a mass-assignment (no strong-parameters) update that writes a privileged field
- Server-enforced authorization versus cosmetic UI locks
- Recognising and fingerprinting Ruby ERB server-side template injection
- Turning ERB SSTI into command execution to read a file
What You'll Gain
- A working Ruby ERB SSTI to RCE payload (<%= `...` %>)
- The mass-assignment-to-admin escalation pattern in a params-merge update
- The habit of testing every reflected field, including a report title, as a template sink