James Cao
DreamHack - blind-command

DreamHack - blind-command Web Challenge Write-up

Room / Challenge: blind-command (Web) Metadata Author: jameskaois CTF: DreamHack Challenge: blind-command (web) Link: https://dreamhack.io/wargame/challenges/73 Level: 2 Date: 10-11-2025 Goal My Solution The app is simple with just one app.py: #!/usr/bin/env python3 from flask import Flask, request import os app = Flask(__name__) @app.route('/' , methods=['GET']) def index(): cmd = request.args.get('cmd', '') if not cmd: return "?cmd=[cmd]" if request.method == 'GET': '' else: os.system(cmd) return cmd app.run(host='0.0.0.0', port=8000) It is only one route that we can leverage. It needs us to have cmd arguments which is executed by os.system(cmd) however there is a check: ...

November 10, 2025 · 1 min
DreamHack - web-ssrf

DreamHack - web-ssrf Web Challenge Write-up

Room / Challenge: web-ssrf (Web) Metadata Author: jameskaois CTF: DreamHack Challenge: web-ssrf (web) Link: https://dreamhack.io/wargame/challenges/75 Level: 2 Date: 10-11-2025 Goal Using image viewer service to capture the flag. My Solution You can download and examine the source code here The source code has one main app.py which is the file runs the application, there is a route that we have to pay attention to /img_viewer: @app.route("/img_viewer", methods=["GET", "POST"]) def img_viewer(): if request.method == "GET": return render_template("img_viewer.html") elif request.method == "POST": url = request.form.get("url", "") urlp = urlparse(url) if url[0] == "/": url = "http://localhost:8000" + url elif ("localhost" in urlp.netloc) or ("127.0.0.1" in urlp.netloc): data = open("error.png", "rb").read() img = base64.b64encode(data).decode("utf8") return render_template("img_viewer.html", img=img) try: data = requests.get(url, timeout=3).content img = base64.b64encode(data).decode("utf8") except: data = open("error.png", "rb").read() img = base64.b64encode(data).decode("utf8") return render_template("img_viewer.html", img=img) Firstly, I tried several payloads to get the flag.txt content like /flag.txt, /static/../flag.txt, … however all of them returns this base64 encoded: ...

November 10, 2025 · 2 min
TryHackMe Putting It All Together Room

TryHackMe - Putting It All Together Room Walkthrough

Overview Room URL: https://tryhackme.com/room/puttingitalltogether Difficulty: Easy Time to complete: 15 Walkthrough 1. Putting It All Together No answer needed! 2. Other Components What can be used to host static files and speed up a clients visit to a website? => Answer: CDN What does a load balancer perform to make sure a host is still alive? => Answer: health check What can be used to help against the hacking of a website? ...

November 9, 2025 · 1 min
TryHackMe How Websites Work Room

TryHackMe - How Websites Work Room Walkthrough

Overview Room URL: https://tryhackme.com/room/howwebsiteswork Difficulty: Easy Time to complete: 25 Walkthrough 1. How websites work What term best describes the component of a web application rendered by your browser? => Answer: Front End 2. HTML One of the images on the cat website is broken - fix it, and the image will reveal the hidden text answer! Change the <img src='img/cat-2'> to <img src='img/cat-2.jpg'>: => Answer: HTMLHERO Add a dog image to the page by adding another img tag (<img>) on line 11. The dog image location is img/dog-1.png. What is the text in the dog image? ...

November 9, 2025 · 1 min
TryHackMe Linux Strength Training Room

TryHackMe - Linux Strength Training Room Walkthrough

Overview Room URL: https://tryhackme.com/room/linuxstrengthtraining Difficulty: Easy Time to complete: 45 Walkthrough 1. Intro No answer needed! 2. Finding your way around linux - overview What is the correct option for finding files based on group => Answer: -group What is format for finding a file with the user named Francis and with a size of 52 kilobytes in the directory /home/francis/ => Answer: find /home/francis -type f -user Francis -size 52k ...

November 9, 2025 · 6 min
TryHackMe Toolbox Vim

TryHackMe - Toolbox Vim Room Walkthrough

Overview Room URL: https://tryhackme.com/room/toolboxvim Difficulty: Easy Time to complete: 45 Walkthrough 1. Task 1 No answer needed! 2. Task 2 How do we enter "INSERT" mode? => Answer: i How do we start entering text into our new Vim document? => Answer: typing How do we return to command mode? => Answer: esc How do we move the cursor left? => Answer: h How do we move the cursor right? ...

November 9, 2025 · 3 min
DreamHack - Mango

DreamHack - Mango Web Challenge Write-up

Room / Challenge: Mango (Web) Metadata Author: jameskaois CTF: DreamHack Challenge: Mango (web) Link: https://dreamhack.io/wargame/challenges/90 Level: 2 Date: 07-11-2025 Goal Get the flag by leveraging blind NoSQL Injection. My Solution You can download and examine the source code here. The web app just have one main.js file to examine: const express = require('express'); const app = express(); const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/main', { useNewUrlParser: true, useUnifiedTopology: true, }); const db = mongoose.connection; // flag is in db, {'uid': 'admin', 'upw': 'DH{32alphanumeric}'} const BAN = ['admin', 'dh', 'admi']; filter = function (data) { const dump = JSON.stringify(data).toLowerCase(); var flag = false; BAN.forEach(function (word) { if (dump.indexOf(word) != -1) flag = true; }); return flag; }; app.get('/login', function (req, res) { if (filter(req.query)) { res.send('filter'); return; } const { uid, upw } = req.query; db.collection('user').findOne( { uid: uid, upw: upw, }, function (err, result) { if (err) { res.send('err'); } else if (result) { res.send(result['uid']); } else { res.send('undefined'); } }, ); }); app.get('/', function (req, res) { res.send('/login?uid=guest&upw=guest'); }); app.listen(8000, '0.0.0.0'); We have to leverage /login route to get the flag. There is a filter function that prevents us from use admin, dh and admi in the route. For example, when we visit /login?uid=admin&upw=DH{ received filter: ...

November 8, 2025 · 2 min
TryHackMe Linux Privesc Room

TryHackMe - Linux Privesc Walkthrough

Overview Room URL: https://tryhackme.com/room/linuxprivesc Difficulty: Medium Time to complete: 75 Walkthrough 1. Deploy the Vulnerable Debian VM Deploy the machine and login to the "user" account using SSH. sudo openvpn <file>.ovpn No answer needed! Run the "id" command. What is the result? user@debian:~$ id uid=1000(user) gid=1000(user) groups=1000(user),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev) => Answer: uid=1000(user) gid=1000(user) groups=1000(user),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev) 2. Service Exploits No hints needed! 3. Weak File Permissions - Readable /etc/shadow What is the root user's password hash? ...

October 27, 2025 · 3 min
TryHackMe Network Traffic Basics Room

TryHackMe - Network Traffic Basics Walkthrough

Overview Room URL: https://tryhackme.com/room/networktrafficbasics Difficulty: Easy Time to complete: 60 Walkthrough 1. Introduction No hints needed! 2. What is the Purpose of Network Traffic Analysis? What is the name of the technique used to smuggle C2 commands via DNS? => Answer: DNS Tunneling 3. What Network Traffic Can We Observe? Look at the HTTP example in the task and answer the following question: What is the size of the ZIP attachment included in the HTTP response? Note down the answer in bytes. ...

October 27, 2025 · 2 min
QnQSec CTF - Secure Letter

QnQSec CTF - Secure Letter Writeup

Room / Challenge: Secure-Letter (Web) Metadata Author: jameskaois CTF: QnQSec CTF 2025 Challenge: Secure-Letter (web) Target / URL: http://161.97.155.116:3001/ Points: 50 Date: 20-10-2025 Goal We have to get the flag by using XSS to get the flag from bot. My Solution This solution is written after the server has beed shut down, so I will use my mind. First let’s examine the source code, there is a route that we can use to inject Javascript code (XSS): /letter route ...

October 27, 2025 · 2 min