CPCTF - mirage Writeup¶
题目信息¶
- 比赛: CPCTF
- 题目: mirage
- 类别: Web
- 难度: 简单
- 附件/URL: 在线靶机
- 附件链接: 无附件
- Flag格式:
CPCTF{...} - 状态: 已解
Flag¶
CPCTF{CH4R4C73R5_4L50_D159U153}
解题过程¶
1. 初始侦察/文件识别¶
- 题面是:“复制并粘贴正确的flag!”
- 提示也非常直接:
- 如果你复制“看起来正确”的 flag,会得到虚假 flag
- 可以逐个复制其他字符串
- 也可以尝试全部复制、搜索或使用开发者工具
- 打开页面后,能看到很多“长得像 flag”的字符串,但题目名本身叫
mirage,已经暗示这是视觉伪装题,眼睛看到的不一定是真的。
2. 关键突破点一:先别信显示效果,要看源码和原始文本¶
- 这题最容易的误区是只盯着页面上看起来最像 flag 的那一行。
- 但提示已经说明:看起来正确的内容会对应虚假 flag。
- 所以第一步就不该继续点选某一行,而应该直接换思路:
- 全选页面内容后粘贴到本地文本编辑器
- 搜索
CPCTF{ - 或者直接打开开发者工具 / 查看页面源码
- 一旦进入源码视角,就能发现真正的问题根本不在后端,而在前端渲染层。
3. 关键突破点二:页面用自定义字体伪装字符外观¶
- 页面源码里直接内联了一个自定义字体:
@font-face {
font-family: "Mirage";
src: url("data:font/woff2;base64,...");
}
- 同时页面正文和每个 flag 元素都使用这个字体:
body, .flag {
font-family: "Mirage", monospace;
}
- 这说明页面上的可见字符,很可能不是“真实文本长什么样就显示成什么样”,而是通过 glyph 映射把原始字符伪装成另一套外观。
- 也就是说:
- 你眼睛看到的是字体渲染后的假象
- DOM / 源码里的文本才是真正可复制、可搜索的内容
4. 获取 Flag¶
- 继续看源码可以发现,页面里的多条字符串其实是由一段前端 JS 数组直接注入 DOM:
[
"TGT7D{I_L0VE_M1KU_H4T5UN3}",
...
"CPCTF{CH4R4C73R5_4L50_D159U153}",
...
].forEach((flag, i) => {
const div = document.createElement("div");
div.className = "flag";
div.textContent = `${flag}`;
container.appendChild(div);
});
- 这里关键点有两个:
- 使用的是
textContent,说明 DOM 里的原始字符串没有被额外编码 - 真正的
CPCTF{...}已经明文写在源码数组里 - 所以根本不需要逐条肉眼比对,只要在源码或全文复制结果里搜索
CPCTF{,就能直接定位真实 flag:
CPCTF{CH4R4C73R5_4L50_D159U153}
攻击链/解题流程总结¶
打开页面 -> 意识到视觉结果不可信 -> 查看源码 / 开发者工具 / 全文复制 -> 搜索 CPCTF{ -> 发现前端数组中的真实 flag -> 提交答案
漏洞分析 / 机制分析¶
根因¶
- 真实 flag 被直接下发到了前端页面源码中。
- 页面只是依靠自定义字体改变 glyph 外观,让原始字符串“看起来像别的内容”。
- 这种伪装只作用于显示层,无法真正隐藏 DOM 中的底层文本。
影响¶
- 任何会查看源码、搜索文本、复制全文或使用开发者工具的用户,都能绕过视觉伪装直接找到真实 flag。
- 在真实业务中,如果把敏感信息直接发给前端,再靠 CSS / 字体 / 混淆做“隐藏”,同样不能提供真正安全性。
修复建议(适用于漏洞类题目)¶
- 敏感数据不要直接出现在前端源码、DOM 或静态资源里。
- 不要把自定义字体、CSS 隐藏、前端混淆当作安全边界。
- 如果数据需要保护,应由服务端在满足权限条件后再返回。
知识点¶
- 自定义字体与 glyph 映射伪装
- DOM 原始文本与视觉渲染结果可能不一致
- 查看源码 / 开发者工具 / 全文搜索在前端题中的价值
使用的工具¶
- 浏览器开发者工具 — 查看 Elements / Sources / 全局搜索
- 查看页面源码 / 抓取 HTML — 直接读取原始前端代码
- Python 3 — 自动抓取页面并提取
CPCTF{...}
脚本归档¶
- Python:
CPCTF_mirage.py - 说明:脚本会直接抓取页面 HTML,并在源码中搜索唯一真实的
CPCTF{...}
命令行提取关键数据(无 GUI)¶
python CTF_Writeups/scripts_python/CPCTF_mirage.py
推荐工具与优化解题流程¶
这题的重点不是“更仔细地看页面”,而是尽快跳出视觉层,直接查看原始文本和源码。
工具对比总结¶
| 工具 | 适用阶段 | 本题耗时 | 优点 | 缺点 |
|---|---|---|---|---|
| 全文复制 + 本地搜索 | 初筛 | 秒级 | 不依赖 DevTools,最快看到真实文本 | 页面内容多时不如源码定位直接 |
| 浏览器开发者工具 | 正解 | 秒级 | 可直接查看 DOM、源码和内联字体 | 需要会用搜索面板 |
| Python 抓取脚本 | 自动化复现 | 秒级 | 稳定、可归档、适合仓库保存 | 需要写少量代码 |
推荐流程¶
推荐流程:先观察页面与提示 -> 立即切换到源码 / DevTools / 全文复制搜索 -> 搜索 CPCTF{ -> 直接取出前端数组中的真实 flag。
工具 A(推荐首选)¶
- 安装:浏览器自带开发者工具
- 详细步骤:
- 打开页面后按
F12 - 查看
Sources或Elements - 全局搜索
CPCTF{ - 直接读取源码中真实 flag
- 优势:最贴近题目提示,也最容易看清自定义字体伪装机制
工具 B(可选)¶
- 安装:Python 3
- 详细步骤:
- 抓取页面 HTML
- 用正则提取
CPCTF{...} - 去重并输出唯一结果
- 优势:适合自动化归档,也能证明题目不依赖页面视觉层