A few days ago, HackTheBox updated the list of available retired boxes, deactivating some while re-activating others. One of the boxes they reactivated happened to be the second box in my list of OSCP-Like Linux systems, affectionately named “Brainfuck.” With such a monicker, I assumed this machine would be quite challenging, and based on the reviews by other users who had completed the challenge, it seemed my predictions were correct:

Brainfuck Difficulty

I also saw that Brainfuck was considered a more “CTF-Like” system than the boxes I’d targeted so far:

Brainfuck CTF-Like

For those of you who aren’t a part of the hacker/gamer crowd, “CTF” stands for Capture the Flag. Capture the Flag began as an outdoor game wherein two opposing teams attempted to defend their “home base” while also trying to infiltrate their opponent’s base and steal their flag. This game was later adapted into computer games, where users could play against each other on the internet in virtual arenas. Most recently, this game was adopted by hackers and became an incredibly popular competitive sport at hacker conventions and online.

In a hacker CTF, a computer is configured with certain vulnerabilities, such as outdated software or weak passwords, and “flags” are planted on the system in various places, each worth a different number of points based on the difficulty of collecting each flag. Hackers compete against each other to try to hack into the machine and collect the flags, aiming to be the first to collect all the flags and/or achieve the highest score.

Hacker CTFs are often more tricky than what you might find “in the wild,” as they’re designed to be more like a game than a real-world simulation. With that in mind, when I saw that Brainfuck was more “CTF-Like” than some the previous systems I’d attacked, I figured I was in for quite a challenge. (After all, they wouldn’t call it “Brainfuck” for nothing.)

Enumeration

I started this challenge as I always do, by scanning the target IP with nmap to see what services were running and look for possible avenues of attack. I executed my typical script scan using nmap -A 10.10.10.17 and also performed a UDP scan with nmap -sU 10.10.10.17. It would be helpful to do a full-range TCP scan as well, but that scan would take longer, so I went for the faster scans first, so I could start working on those results before the full-range scan came back. When I received the results of my script-scan, I found a few points of interest:

root@kali:~# nmap -A 10.10.10.17
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-22 20:30 EDT
Nmap scan report for 10.10.10.17
Host is up (0.068s latency).
Not shown: 995 filtered ports
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol
                       2.0)
    [...]
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: CAPA USER SASL(PLAIN) AUTH-RESP-CODE UIDL TOP RESP-CODES
                     PIPELINING
143/tcp open  imap     Dovecot imapd
|_imap-capabilities: more IMAP4rev1 Pre-login IDLE AUTH=PLAINA0001 LITERAL+ have
                     OK post-login ENABLE capabilities listed ID LOGIN-REFERRALS
                     SASL-IR
443/tcp open  ssl/http nginx 1.10.0 (Ubuntu)
|_http-server-header: nginx/1.10.0 (Ubuntu)
|_http-title: Welcome to nginx!
| ssl-cert: Subject: commonName=brainfuck.htb/organizationName=Brainfuck Ltd./
                     stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.brainfuck.htb, DNS:sup3rs3cr3t.brainfuck.htb
    [...]
Warning: OSScan results may be unreliable because we could not find at least 1
open and 1 closed port
    [...]
Service Info: Host:  brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernel
    [...]
OS and Service detection performed. Please report any incorrect results at
https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 53.69 seconds

The first thing I noticed was that while port 80 wasn’t open, port 443 (HTTPS) was, and it was running nginx 1.10.0. I also noticed that nmap had returned a few interesting DNS entries. It’s not uncommon for HTB machines to use the .htb Top-Level Domain (TLD), and sure enough, this machine identified itself as brainfuck.htb in its SSL certificate. However, it also had entries for www.brainfuck.htb and sup3rs3cr3t.brainfuck.htb, the latter of which I was most interested in. Based on the results, it appeared as if the HTTPS server returned the default nginx welcome page, since the title of the page was Welcome to nginx! However, it was quite possible that browsing to the page with one of the specified domains would return different results.

After starting the full-range SYN scan using nmap -sS -p- 10.10.10.17, I checked on my UDP scan to see if it had finished. Sure enough, it had, but there were no interesting results. I decided to go ahead and check the website to see if my suspicions were correct. I edited my /etc/hosts/ file to set the IP address for brainfuck.htb, then opened my browser and visited https://brainfuck.htb/.

Brainfuck WordPress Page

What I found was a WordPress page, with a single post that mentioned SMTP integration and listed an email address: orestis@brainfuck.htb. I saved the username orestis in a file called usernames.txt in case I needed to use it for brute-forcing the open SSH service later. I also added admin to the user list, since the post itself was made by a user named admin.

Since this was a WordPress installation, I knew there would be a login page at https://brainfuck.htb/wp-login.php, so I went there to check it out. It was as I expected, a basic WordPress login page:

WordPress Login

Looking at the page source, I saw that this appeared to be WordPress version 4.7.3:

WordPress Version

I made a note to check for vulnerabilities in this version of wordpress, but I first wanted to see if there was something interesting at sup3rs3cr3t.brainfuck.htb. As before, I had to add an entry to the /etc/hosts file, but with that completed, I directed my browser to open https://sup3rs3cr3t.brainfuck.htb/, where I found a Super Secret Forum:

Super Secret Forum

In the source code to this page, I found multiple references to flarum, which sounded to me like the name of a forum software. Sure enough, a quick Google search led me to the Flarum Homepage, with the tagline “Forums made simple.” I added another note to check for vulnerabilities in the Flarum software, but first I would need to look for version information and investigate the rest of the site to see what other information I might uncover.

While I wasn’t able to find any obvious version information, I was able to see that the usernames admin and orestis had both been used on the forums, further reinforcing my belief that they might be usernames worth investigating.

I took a moment to re-visit the Flarum Homepage, where I saw a Documentation page. There was a section called “Troubleshooting,” where I found that Flarum records its logs in storage/logs/flarum.log, so I checked the /storage/ and /storage/logs/ directories, both of which returned 403 Forbidden errors. But sure enough, when I checked /storage/logs/flarum.log, it prompted me to download a file. I saved the file and browsed the logs, noticing that there were some problems with the Zend framework. There were a few lines mentioning errors in a file called DispatchRoute.php, so I opened that script in my browser and got an error message saying “No input file specified.” If the script required a file as input, could I abuse that to execute malicious code somehow? I made a note to check it out.

There were many other files mentioned in the flarum.log file, most related to the Zend framework. I made another note to check on this framework to see if there were any vulnerabilities, and wrote a quick script to parse the log for a list of PHP files mentioned in the log. It returned the following entries, all located in the web server’s root directory (/var/www):

root@kali:~# cat urls.txt | sed 's/\/var\/www//g'
/secret/admin.php
/secret/index.php
/secret/vendor/flarum/core/src/Admin/Middleware/RequireAdministrateAbility.php
/secret/vendor/flarum/core/src/Core/Access/AssertPermissionTrait.php
/secret/vendor/flarum/core/src/Http/AbstractServer.php
/secret/vendor/flarum/core/src/Http/Middleware/AuthenticateWithSession.php
/secret/vendor/flarum/core/src/Http/Middleware/DispatchRoute.php
/secret/vendor/flarum/core/src/Http/Middleware/ParseJsonBody.php
/secret/vendor/flarum/core/src/Http/Middleware/RememberFromCookie.php
/secret/vendor/flarum/core/src/Http/Middleware/SetLocale.php
/secret/vendor/flarum/core/src/Http/Middleware/StartSession.php
/secret/vendor/zendframework/zend-diactoros/src/Server.php
/secret/vendor/zendframework/zend-stratigility/src/Dispatch.php
/secret/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php
/secret/vendor/zendframework/zend-stratigility/src/Next.php

I browsed to https://sup3rs3cr3t.brainfuck.htb/secret/index.php and again received the “No input file specified” error. The same happened when I visited /secret/admin.php. I decided to put this route of inquiry aside, and see if there were any known exploits for the services I’d uncovered so far.

Fishing for Exploits

As usual, I turned to searchsploit to help me find applicable exploits to known services. I found a couple interesting results, but nothing I could truly leverage. I discovered that the OpenSSH 7.2p2 service was vulnerable to a username enumeration attack, but after attempting to use this vulnerability to verify the usernames I’d saved in my usernames.txt file, I found that the enumeration was unreliable. (I would later discover that this was likely due to the fact that OpenSSH had been configured to disallow password-based logins.)

I also found a couple vulnerabilities in the Zend framework, but nothing I could use right away.

After an hour and a half of browsing through searchsploit results, I felt I’d been chasing after phantoms. Nothing seemed to jump out at me.

I decided that perhaps I needed a little more enumeration. I saw that the Postfix SMTP server had the VRFY option enabled, which would allow me to check whether users were registered with the email system. I logged in and requested some information:

root@kali:~# telnet 10.10.10.17 25
Trying 10.10.10.17...
Connected to 10.10.10.17.
Escape character is '^]'.
HELO brainfuck.htb
220 brainfuck ESMTP Postfix (Ubuntu)
250 brainfuck
VRFY root
252 2.0.0 root
VRFY admin
550 5.1.1 <admin>: Recipient address rejected: User unknown in local
                   recipient table
VRFY orestis
252 2.0.0 orestis
^]
telnet> q
Connection closed.

Based on this response, I could see that the orestis user was registered to the mail system, but the admin user was not. This suggested that the orestis user would be more likely to have an SSH account as well.

Deciding to scan the web server for interesting directories, I fired up dirbuster and set it to scan https://sup3rs3cr3t.brainfuck.htb/ to see what information it could dig up. Meanwhile, I checked up on the full-range nmap scan I’d started earlier, only to find that there were no additional ports that weren’t already in my previous search. So I turned back to searchsploit to see if I could find anything relating to postfix or dovecot while dirbuster was doing its work.

Failshock

I found a reference to Shellshock, and decided to check it out. I didn’t know what version of Postfix was running, so it was a shot in the dark, but I figured it couldn’t hurt to try. I copied the script to my local folder with searchsploit -m exploits/linux/remote/34896.py, renamed the file to shellshock_smtp.py, and took a look.

root@kali:~# python shellshock_smtp.py
shellshock_smtp.py <target> <command>

Simple enough. I just needed a way to test whether it would work. I opened wireshark and set it to monitor my HackTheBox VPN connection for ICMP ping packets. First, I tested to make sure wireshark was working by pinging the target machine with ping -c3 10.10.10.17. Sure enough, the traffic appeared in wireshark:

wireshark ping test

It was time to test out the Shellshock script.

root@kali:~# python shellshock_smtp.py 10.10.10.17 "ping -c 3 10.10.14.8"

I watched as the request was sent and accepted by the remote SMTP server. I waited for those incoming ICMP packets… And nothing came. It appeared as if Shellshock wouldn’t work. I set the script aside and moved on.

Enumeration, Part 2

I went online and searched for “WordPress vulnerabilities” and after some searching discovered a tool I hadn’t heard of before called wpscan, which (lucky me) was included with Kali. I set it to scan the target site, then went back to dirbuster to see what it had found. Unfortunately, it hadn’t found much on the sup3rs3cr3t subdomain, so I started it up again scanning the base brainfuck.htb domain. Then I turned back to wpscan. It returned a pretty long list of results, including a few interesting potential exploits. Most of them seemed to require authentication or were XSS attacks, neither of which would be of much use to me. I noticed, however that wpscan had identified a plugin: WP Support Plus Responsive Ticket System. I remembered seeing some plugins listed when I did my searchsploit scan, so I went back and repeated the search, targeting WP Support Plus:

root@kali:~# searchsploit wordpress 7.1 wp support plus
--------------------------------------- ----------------------------------------
 Exploit Title                         |  Path
                                       | (/usr/share/exploitdb/)
--------------------------------------- ----------------------------------------
WordPress Plugin WP Support Plus Respo | exploits/php/webapps/40939.txt
WordPress Plugin WP Support Plus Respo | exploits/php/webapps/41006.txt
--------------------------------------- ----------------------------------------
Shellcodes: No Result
Papers: No Result

There were two results, a privilege escalation (privesc) and an SQL injection (SQLi). I decided to check them both out, so I copied them to my local folder and read their contents. I expected that the privesc attack wouldn’t be of much use, since it would typically require me to be logged in as a user, but perhaps the SQLi would be useful.

The SQLi exploit included a proof-of-concept (PoC) in the form of an HTML form that could be included on the page. To test this out, I used Firefox’s developer tools to edit the HTML of the page in-place, replaced the content of the post with the form, and clicked the submit button.

After submitting the form, the response I got was underwhelming… It was simply the number 0, by itself, on the page. I tried a number of possible queries, but each time the result was simply 0. Some queries took longer than others, and I wondered if perhaps the queries were running successfully without returning visible results. So I tried a query to create an admin user in the database, as detailed in a tutorial I read. Then I attempted to login… With no success.

I’d been barking up the wrong tree yet again. This challenge was definitely living up to its name.

A Foot in the Door

I decided to check out the second exploit, involving privilege escalation. As it happens, the exploit claimed to allow the attacker to log in as any user, without using any credentials. Worth a shot! So I went back to the WordPress page, once again edited the HTML to add the form specified in the exploit, and clicked submit. After the exploit was completed, I returned to the main page, and (much to my surprise), I was logged in as the admin!

admin achieved

Finally, I was one step closer to my goal. While it took a lot of searching, it felt good to have achieved something, no matter how small.

It was around this time that my internet connection died and I had to reboot and re-exploit the wordpress page. This wasn’t the first time I’d experienced such an issue, but it was frustrating that it had to happen right as I was making some progress. Before rebooting, I checked dirbuster; it hadn’t found anything of which I wasn’t already aware.

Enumeration, Part 3

With admin access to the WordPress page, I proceeded to explore what new information was available to me. I went to the Plugins page and found that Easy WP SMTP was installed, allowing users to send email via SMTP. I recalled some of the email vulnerabilities I’d seen prior, and decided to investigate whether I could abuse this service.

I went to the settings page for the Easy WP SMTP plugin, and found that there was a SMTP password field that had been auto-populated. By viewing the source code to the page, I was able to find the password entered therein: kHGuERB29DNiNE. I added this to a passwords.txt file for later, noting that the password had been assigned to the orestis user for accessing SMTP. I also noticed that I could manually update the From Email Address field, which meant that I might be able to exploit one of the vulnerabilities I’d seen before in order to get a shell.

But first, with a username and password combination in-hand, I decided to see if I could log into SSH:

root@kali:~# ssh orestis@10.10.10.17
The authenticity of host '10.10.10.17 (10.10.10.17)' can't be established.
ECDSA key fingerprint is SHA256:S+b+YyJ/+y9IOr9GVEuonPnvVx4z7xUveQhJknzvBjg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.10.10.17' (ECDSA) to the list of known hosts.
orestis@10.10.10.17: Permission denied (publickey).

It would seem that I could only gain access with orestis’ public key. I would either need to find a way to download the user’s key or upload one of my own. I made a note of it, and went back to investigating the SMTP exploit.

Unfortunately, the scripts I’d found didn’t work, and neither did any of my attempts to exploit the Easy WP SMTP plugin by hand. But I wouldn’t let this discourage me. With admin access to the WordPress page, I decided to see if it would be possible to upload a new plugin to the site. If so, I could upload a wordpress shell plugin and gain command-line access that way.

No such luck; the upload directory was restricted.

Mail Snooping

I decided to try accessing the user’s email account with an email client. I had the user’s credentials, after all. Perhaps there was some email stored that might offer me some insight?

I installed sylpheed, a lightweight email client, and logged into Orestis’ account, where I found two emails waiting for me. The first was about the WordPress site, telling me how to log in. What stood out to me, however, was the X-Mailer header, which specified that the email had been sent via PHPMailer 5.2.22:

PHPMailer Version

No wonder my previous exploit attempts hadn’t worked! The PHPMailer exploit I’d been using only worked for versions prior to 5.2.20. Returning to searchsploit, I checked for PHPMailer vulnerabilities, and discovered that none were applicable to the installed version.

Moving on, I checked the next email. It was a message regarding the secret forum, informing me of the admin username/password:

Forum Credentials

This password was probably randomly-generated, but I added it to my passwords.txt file anyway. One step closer! It was time to log in to the forum and see what I could learn.

Accessing the forum with the username/password I’d learned from the email account, I was presented with some new forum topics:

New Forum Topics

First, I visited the SSH Access thread, where I found the following discussion:

SSH Passwords Disabled

Just as I had discovered, the SSH password login had been disabled, and the only way to gain access was with SSH keys. Yet the thread where they discussed SSH keys was “encrypted”:

Key Conversation

It looked like I had a crypto challenge on my hands. I noticed that every post made by Orestis had the tagline Orestis - Hacking for fun and profit, and in the encrypted text there was a similar tagline after every post Orestis made, though the text was different in each one. Clearly it wasn’t a direct substitution cipher, so I went online and did some research regarding rolling ciphers, and stumbled upon the Vigenere Cipher, which was aptly explained on the dcode.fr website. With their handy decoder grid on-hand, I went to work reversing the key used to encrypt their text. Sure enough, I found the key: FUCKMYBRAIN. Go figure. Here’s a transcript:

Orestis: Hey give me the url for my key bitch :)
         Orestis - Hacking for fun and profit

Admin:   Say please and i just might do so...

Orestis: Pleeeease....
         Orestis - Hacking for fun and profit

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

Orestis: No problem, I'll brute force it ;)
         Orestis - Hacking for fun and profit

Right away I copy-pasted the URL into my browser and downloaded the id_rsa file and put it in my ~/.ssh directory. As Orestis had stated, I still didn’t have the password for the key, so I would have to brute-force it. First things first, though; I wanted to set up my ~/.ssh/config file so that I would automatically use the key when logging in to the remote host. I created the file and configured it as follows:

root@kali:~/.ssh# cat config
Host brainfuck.htb
Hostname brainfuck.htb
Port 22
User orestis
IdentityFile ~/.ssh/id_rsa

Before I could use the key, I needed to change its permissions, so I ran chmod 700 ~/.ssh/id_rsa to ensure they were set properly. With that done, I needed to find a way to brute-force the passphrase. Looking online, all the guides I found used a tool called ssh2john to convert the SSH key into a format readable by John the Ripper, but unfortunately this tool wasn’t available on Kali by default. After a little Googling, however, I was able to find the tool on github. With this tool, I was able to convert the key into a format that John could read:

root@kali:~/.ssh# ./ssh2john.py id_rsa > john.key

Now it was simply a matter of letting John do all the heavy lifting. I decided to start with a wordlist first, rather than a full brute-force attack, as it would be faster. I unzipped the /usr/share/wordlists/rockyou.txt.gz file and used it as my wordlist:

root@kali:~/.ssh# gunzip /usr/share/wordlists/rockyou.txt.gz
root@kali:~/.ssh# john --wordlist=/usr/share/wordlists/rockyou.txt john.key
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 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 2 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
3poulakia!       (id_rsa)
1g 0:00:00:10 DONE (2019-04-23 08:14) 0.09794g/s 1404Kp/s 1404Kc/s
                                      1404KC/sa6_123..*7¡Vamos!
Session completed

Much to my surprise, John seemed to find the password right away: 3poulakia! I attempted to SSH into the target system using the new-found password, and bingo! I had access:

root@kali:~# ssh brainfuck.htb
Enter passphrase for key '/root/.ssh/id_rsa':
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-75-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 packages can be updated.
0 updates are security updates.


You have mail.
Last login: Wed May  3 19:46:00 2017 from 10.10.11.4
orestis@brainfuck:~$

Of course, at this point, my first action was to get the user flag:

orestis@brainfuck:~$ ls -l
total 20
-rw------- 1 orestis orestis  619 Apr 29  2017 debug.txt
-rw-rw-r-- 1 orestis orestis  580 Apr 29  2017 encrypt.sage
drwx------ 3 orestis orestis 4096 Apr 23 13:43 mail
-rw------- 1 orestis orestis  329 Apr 29  2017 output.txt
-r-------- 1 orestis orestis   33 Apr 29  2017 user.txt
orestis@brainfuck:~$ cat user.txt
2c11cfbc5b959f73ac15a3310bd097c9

With the user flag properly claimed, I felt exhausted. I’d spent hours getting to this point, and needed to take a break. I logged out of the system, disconnected from HTB, and shut down for the night.

(To see the thrilling conclusion, please read Part 2 of the walkthrough.)