周三下午,一位选手打开 BroncoCTF 的报名页面,题目叫“密钥大师”。没有文件,没有二进制,只有一个网址 https://broncosec.com/BroncoCTF。规则只写明旗标格式是 bronco{XXXX...},但旗标本身被拆成 8 个编号片段,混在网站各处,需要全部找齐并按序拼合。
挑战开始,最简单的一步是直接请求页面 HTML。浏览器渲染的正文里藏着大量线索,4 个片段就躺在静态标记中——从图片的 alt 文字、标题属性、查询参数到不寻常的文件名,这些片段在源码中一目了然。
第五个片段藏得略深一点。“关于比赛”段落里有一句“BroncoCTF 2026 将是我们举办的第五届 CTF……”,其中的“2026”被伪装成普通文本,实际是一个指向 /7.txt 的超链接。用 curl 抓回那个文件,里面赫然写着“7 - _w0rr135”,第七片就此到手。
还缺三片。它们从未出现在静态 HTML 里,而是由 JavaScript 事件处理器在运行时才注入页面。常规的 curl 请求永远看不到这些内容。于是,从页面源码中找出 Next.js 应用的脚本分块,逐个下载 /_next/static/chunks/ 下的哈希文件名,再用 grep 搜索“bronco{”或“- ”模式,立刻锁定了三个点击处理逻辑。
第二片挂在一个“flags”文字上:点击后,一个 onClick 函数会向一个 id 为“addtext”的隐藏 div 追加文本“2 - 3y_y0u_f”,同时播放音效。这个 div 在未点击前是空的,静态抓取只会看到空白。
第四片藏在 表情符号的点击事件里。点击后,页面会设置名为“KEY4”的 Cookie,其值就是“4 - m_4ll_w1”,同时在表情旁追加 作为确认。第五片则更隐蔽,一个 React 组件在挂载时通过 useEffect 把片段以注释形式动态注入 DOM,同样只有客户端执行后才会现身。
静态抓取给出了半程答案,但剩下的旗标片段只存在于浏览器的运行态里。挑战的设计把“看源码就够了”的惯性打破,提醒我们现代网页的客户端 JavaScript 才是最后的战场。如果只依赖一次 curl 的快照,那些被事件驱动、被 Cookie、被注释隐藏的信息永远也不会冒出来。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.