Offlinea — HTB Challenge
retleave·Apr 21, 2026·9 min read
Offlinea - HTB Challenge
Info
- Category: Web
- Difficulty: Medium
- Key Topics: HTTP parameter pollution, PHP vs Flask parameter parsing, Python format string injection, SSRF filter bypass, JWT forgery
- Environment: Python 3.12 (slim-bookworm), PHP, headless Chrome, Flask, SQLite
Abstract
Offlinea presents a dual-stack web application with a PHP frontend (port 8000, public) and a Flask backend (port 5000, internal). The PHP layer accepts URLs from users, validates them against SSRF filters, and forwards the raw query string to the Flask backend, which visits the URL with headless Chrome and generates a PDF. The attack chain exploits three vulnerabilities in sequence: (1) HTTP parameter pollution between PHP and Flask to bypass SSRF validation, (2) Python format string injection via Flask's
logify() function to leak the SECRET_KEY, and (3) JWT forgery with the leaked key to access the protected /bartender endpoint containing the flag. This writeup examines each vulnerability layer, the parser differential that enables the bypass, and the format string injection mechanism.Architecture Analysis
Dual-Stack Design
The application runs under supervisord with two services:
| Service | Port | Technology | Accessibility |
|---|---|---|---|
| PHP Frontend | 8000 | PHP + Apache/nginx | Public (exposed) |
| Flask Backend | 5000 | Flask + Selenium/Chrome | Internal only |
The PHP frontend (
bartender.php) is the only externally accessible component. It receives a URL, validates it, and proxies the request to the Flask backend by appending the raw query string:php
$final_url = $api_scraper . $_SERVER['QUERY_STRING'] . "&time=" . $t;
// e.g., http://127.0.0.1:5000/generate?url=...&name=x&secret=x&time=1234Content Locked
This challenge is still active on HackTheBox. The full writeup will be available after retirement.