从打开 ctfshow 题目列表到彻底上手,我花了一段时间才摸清门道。刚开始那会儿,我面对几千道题完全不知道该从哪里下手,都是盲目点开一道道试,浪费了不少时间。这篇内容里,我把自己的学习路径、踩过的坑以及一些核心题型的拆解思路整理出来,希望能帮你少走一些弯路。
ctfshow 是偏向实战训练的 CTF 练习平台,里面有 Web、Misc、Crypto、Reverse、Pwn 等方向的题目,覆盖基础入门到高阶挑战,尤其适合想系统提升 Web 安全的同学。如果你正在找一条适合自己的刷题路线,或者卡在命令执行、代码执行这类题目上不知道怎么突破,这篇文章应该能给你一些启发。
1. ctfshow 到底是一个什么样的训练场
1.1 平台结构:不仅有题目,还有完整的赛季机制
先说说 ctfshow 的板块设计。和其他 CTF 练习平台不同,ctfshow 的题目并不是简单堆在同一个列表里,而是按"赛事"和"专题"两条线组织起来的。比如早期的 web 入门题目集中在"web 入门"这个模块里,从 web1 到 web100 多题,难度循序渐进,每一题对应一个独立的知识点。后面又拆分出了"web 进阶""代码审计""反序列化""SQL 注入专项"等系列,等于把整个 Web 安全的知识地图拼好了一部分。
平台还有赛季制度,周期性推出新的比赛和题目。这个设计对坚持学习的人来说非常友好,因为赛季结束之后会有排名和积分,相当于给刷题这件事加了一点目标感。我自己的体验是,有了赛制和排名之后,学习动力明显提升,不再像无头苍蝇一样乱点。
1.2 和其他平台对比:为什么我推荐从它开始
很多新手会在 ctfshow、BUUCTF、攻防世界之间纠结,我三个平台都用过,简单说下它们的区别。
| 平台 | 题目量 | 难度梯度 | 适合人群 |
|---|---|---|---|
| ctfshow | 大量,持续更新 | 入门到高阶全覆盖,web 方向特别完整 | 想系统学习 Web 安全的人 |
| BUUCTF | 中等 | 真题为主,难度偏高 | 有基础后去刷真题的人 |
| 攻防世界 | 中等 | 分类明确,但部分老题环境不稳定 | 想接触杂项、逆向等方向的人 |
我的结论是:如果你目标是 Web 安全,尤其是想走渗透测试或安全研发方向,ctfshow 的 web 系列几乎是量身定做的。它的 web 入门题从"查看源码""看响应头"这种最基础的操作开始,逐步深入到命令执行、文件包含、反序列化、代码审计等高阶考点,整个曲线非常平滑,基本不会出现"第一题做完了,第二题直接看不懂"的情况。
1.3 免费与扩展:预算为零也能学得很好
ctfshow 提供了一套免费的基础题库,许多经典的 web 入门题目都可以直接刷。除此之外,平台还提供需要积分或会员解锁的扩展题库,里面包含更多贴近实战的题目和题型。我的建议是,先把免费的基础题刷完,尤其是 web 入门的全部题目,再考虑是否需要深入扩展内容。基础题如果没能全部吃透,直接去碰扩展题,很容易产生挫败感。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从 web 入门第一关说起:一次完整的题目拆解
2.1 web1 这道题究竟在考什么
很多人在 ctfshow 上做的第一道题就是 web1,也是整个 web 入门系列的起点。它考察的内容其实非常简单:你知不知道如何查看一个网页的源码。听起来基础得有点过分,但这道题放在第一关是有原因的。
CTF 的 Web 题目里,flag 可能藏在各种地方——页面源码、响应头、JS 文件、注释、隐藏目录、cookie、数据库、服务器文件,甚至日志和报错信息里。web1 就是先教会你"看源码"这个最基本的操作。它不会给你设置任何绕过障碍,只要你会右键查看源码,或者用浏览器开发者工具的 Elements 面板,就能在 HTML 注释里发现 flag。
2.2 首次做题的完整流程
我建议第一次接触 CTF 的 Web 题时,养成一套固定流程,后面所有题目都会用到:
- 启动靶机:在平台上点击启动,拿到题目对应的 URL 地址。
- 用浏览器打开目标 URL:先正常访问,观察页面内容,看有没有明显的提示。
- 打开开发者工具:按 F12 或者右键选择"检查",切换到 Elements 面板,从上到下翻看 HTML 结构。
- 查看网络请求:切换到 Network 面板,刷新页面,看所有请求和响应的 Header、状态码。
- 尝试右键菜单:有些题目隐藏了右键功能,那就用快捷键或者开发者工具绕过。
对 web1 来说,通常到第三步就能解决了。但不要因为题目简单就跳过后面的步骤,后面的题目会越来越依赖这些基础操作。
2.3 常见误区:一看答案就觉得自己会了
Web 入门题难度低,导致很多人容易犯一个毛病:做不出来就立刻看题解,看完恍然大悟,觉得自己已经会了。但下次遇到同类题,依然做不出来。
我在入门阶段就吃过这个亏。后来我给自己定了一个规矩:一道 Web 题至少尝试 20 分钟,实在解不出来才看题解。看完题解之后,不是直接下一题,而是把解题过程整理成笔记,并且复现一遍。Web 题目非常讲究"做一遍"的肌肉记忆,只靠眼睛看是形成不了这种记忆的。
3. 命令注入与管道符绕过:真正吃透过滤逻辑
3.1 从"shell code executor"说起
在 ctfshow 热词里,出现频率很高的是"shell code executor 管道符绕过过滤"。这其实是 Web 安全中非常经典的一类考点:命令执行漏洞(Command Injection)。当目标站点把用户输入直接拼接到系统命令中执行,且没有做严格的过滤,就会产生命令注入漏洞。
这类题目的典型场景是:页面提供一个输入框,让你传入 IP 地址或文件名,后端代码可能这样写:
php复制<?php
$cmd = "ping -c 1 " . $_POST['ip'];
system($cmd);
?>
正常情况下,输入 127.0.0.1 就能执行 ping 命令。但如果输入的是 127.0.0.1; whoami,在 Linux shell 中,分号表示命令分隔符,前面的 ping 执行完,后面的 whoami 也会跟着执行,这样你就拿到了命令执行权限。
3.2 管道符在 shell 中的特殊含义
管道符 | 是类 Unix 系统里一个极其重要的操作符,作用是把前一个命令的输出作为后一个命令的输入。比如 ls | grep flag,就是把 ls 的结果传给 grep 过滤出包含 flag 的文件名。
在 CTF 场景里,管道符同样可以用来拼接命令。假设后端过滤了分号 ; 和 &&,但没过滤管道符 |,那我们就可以这样绕过:
bash复制127.0.0.1 | whoami
这条命令的意思是:把 ping -c 1 127.0.0.1 的输出结果传给 whoami 执行。虽然 ping 本身会正常执行,但后面 whoami 的结果也会显示在页面上。如果页面没有任何回显,还可以通过管道符把命令结果输出到文件中再访问,或者配合 nc 等工具反弹到自己的监听端口。
3.3 关键字被过滤时的绕过思路
命令注入的题目往往不会让你直接用 cat、flag 这些词,因为开发者通常会做一个黑名单过滤。常见的过滤方式有:
- 过滤命令关键字,比如
cat、ls、whoami - 过滤特殊字符,比如空格、
/、$、反引号 - 过滤参数分隔符,比如
;、|、& - 正则匹配严格模式,直接拦截可疑输入
面对黑名单,我们可以用 Linux shell 的语法特性来绕过。举几个高频的绕过方法:
| 过滤内容 | 绕过思路 | 示例 |
|---|---|---|
| 空格 | 用 ${IFS} 代替空格 |
cat${IFS}/flag |
斜杠 / |
用 $(dirname /etc/passwd) 拼接 |
或使用 cd .. 切换路径 |
cat 命令名 |
命令内联拼接 | c''at、c\at、$(printf "cat") |
分号 ; |
用管道符、换行符、&& 替代 |
ip \n whoami |
反引号/$() |
用管道组合 | ls | base64 |
| 部分字母被过滤 | 用通配符 ? * |
/???/??? 匹配 /bin/cat |
代码层面举个例子。假设后端过滤了 flag 字符串,我们可以用通配符绕过:
bash复制127.0.0.1 | cat /fla*
这条命令在 shell 中会被扩展为 /fla* 匹配所有以 fla 开头的文件,从而拿到 /flag 文件的内容。如果过滤了 cat,还可以尝试 tac(反向输出文件)、more、less、head、tail 等命令。
3.4 除了管道符,还有哪些命令拼接姿势
很多初学者只记住了管道符 |,但实际做题时会发现,过滤规则五花八门,单一姿势不够用。我整理了一套判断流程,遇到命令执行题时按这个思路排查:
- 测闭合:先判断输入是拼接到命令中间还是末尾,尝试闭合引号、括号,比如
" ; whoami、') ; whoami。 - 测命令能否执行:输入
whoami,看页面是否输出用户名,这是验证命令执行最直接的方式。 - 测分隔符:依次尝试
;、|、||、&、&&、换行符%0a、回车%0d,找到哪个没被过滤。 - 测空格:如果系统过滤空格,尝试
${IFS}、$IFS$9、%09(Tab)、{cat,/flag}等替代方式。 - 测关键字:找到被过滤的关键字后,用引号拼接、反斜杠、环境变量拼接、
printf等方式绕过。 - 看回显:如果能直接看到命令输出,很好;如果看不到,考虑写入文件再访问,或者 DNSlog 外带数据。
这个流程本质上是把你当成一个"过滤器探测工具",一步步摸清后端到底拦了什么、没拦什么。很多命令执行题解决起来只是时间问题。
3.5 防御视角:后端到底应该怎么防
刷了足够多的命令注入题之后,要反过来想:开发者怎么写代码才能避免这类漏洞?我在写自己的靶场代码时,总结了几个关键点:
- 优先使用白名单,而不是黑名单。比如 ping 题的参数只允许数字和点,直接用
is_numeric判断。 - 使用安全的执行函数。PHP 里优先用
escapeshellarg()和escapeshellcmd()转义用户输入,或者用shell_exec时避免拼接用户原始输入。 - 把外部输入交给参数化函数。能不用 shell 执行就尽量不用,比如 ping 可以用原生 socket 库实现。
- 限定命令超时时间,防止命令长时间执行,避免被用作跳板进行更多操作。
理解防御思路,反过来能让你更明白进攻时哪些地方是可突破的。两者一起学,效果远比单纯刷绕过姿势好得多。
4. 从入门到进阶的路径规划:别把刷题变成刷量
4.1 分阶段学习法,而非盲目追求数量
ctfshow 的题库数量很大,在没有规划的情况下刷题,很容易陷入"今天做一题,明天做一题,做了几百道还是感觉没入门"的困境。我自己的经验是,把学习分成三个阶段,每个阶段的侧重点完全不同。
第一阶段:熟悉工具与基本套路(web1-web60 左右)
这一阶段的核心目标是熟悉做题流程和基础工具。你要熟练掌握浏览器开发者工具、Burp Suite 的抓包改包、curl 命令行、Python requests 脚本,以及常见的编码工具(URL、Base64、Hex、MD5)。题目本身不难,但工具的熟练度直接决定后面解题效率。我记得自己刚开始用 Burp Suite 时,连 intercept 开关都来回切换不明白,卡了很多低级问题。
建议:每道题不仅仅写出 flag,还要在原理解释区写清楚"这题考的是什么""关键步骤是哪一步""为什么会是这样"。把每一题都当成知识点来整理。
第二阶段:构建知识地图(web进阶与专项训练)
到了这个阶段,你需要有意识地把题目分门别类。比如 SQL 注入类、命令执行类、文件包含类、文件上传类、SSRF 类、反序列化类、代码审计类等。对每一类题目,建立一个独立的笔记,记录:常见考点、触发点、绕过方式、经典 payload、源码审计思路。这就像一个技能树,每做一道题就往对应的节点上填内容,后面遇到新题时,你会很快定位到它属于哪个分支。
在这个阶段,我强烈建议尝试写自动化的解题脚本。比如用 Python 的 requests 库爆破登录、用脚本跑字典、用脚本发送构造好的拨测请求。CTF 题目做到后面,很多都是靠脚本批量测试,手工会非常吃力。
第三阶段:综合实战与模拟赛场
这个阶段可以开始刷 ctfshow 的赛季题,或者把目标从"做对题目"转移到"在限定时间内完成整套卷子"。真实比赛的压力和平时刷题完全不一样,体力和专注度都会影响发挥。我建议每周至少完整参加一次模拟赛,哪怕是平台的周赛也好,目的不是拿名次,而是训练自己在规定时间内合理分配精力。
4.2 面对"目标资产渗透认证"类内容怎么办
ctfshow 的热词里也出现了"目标资产渗透认证"。这个方向其实涉及渗透测试中非常重要的一个概念:授权与合规。在企业做渗透测试,必须获得书面授权,并且严格限定测试范围和测试时间,不能越界,这是职业底线也是法律底线。
CTF 平台上的靶机是专门用于练习的合法环境,你拥有该环境的测试权限,这和真实渗透测试有本质区别。如果你想在后者的方向上发展,除了技术之外,一定先理解授权流程、测试范围界定、报告编写等内容。安全测试的前提永远是合法合规,这一点我希望每个初学者都能记住。
4.3 一题三做,比刷三题更有效
我在刷题过程中形成了一套"一题三做"的方法,效果比盲目刷量好太多:
- 限时独立完成:拿到题目后不看题解,给自己 20-30 分钟,独立尝试所有能想到的方法。
- 做完整理笔记:无论做没做出来,都写一篇笔记,记录题目背景、关键考点、自己的思路链、卡在哪一步、为什么卡住。
- 看看别人的解法:寻找其他人的 writeup,对比自己的思路,看对方用了什么不同的角度。
如果题目特别难,还会隔段时间再做一遍。这个过程看起来慢,但记忆留存率远超单纯刷题。我身边刷题快的人,很多过一个月什么印象都没了,而用一题三做整理过的题目,比如命令注入的绕过方式,至今还能默写出来。
5. 刷题一年后我才总结出来的实操经验
5.1 不要忽视环境搭建和代码审计能力
很多人在 ctfshow 上刷题,只关注"怎么看源码""怎么抓包改包",但忽略了真正拉开差距的两件事:本地环境复现和代码审计能力。
所谓本地环境复现,就是拿到一个题目的源码后,自己在本地搭一套环境,通过改代码、加日志、调试来观察漏洞触发的每一步。这样对漏洞的理解会彻底不同。比如命令执行题,你在本地把源码改成打印完整命令的日志,就能清楚看到自己的输入被拼接成了什么。这种观察是在线上靶机里很难获得的。
代码审计能力则是从"我会用漏洞"升级到"我理解漏洞"。刷题时多关注靶机英文注释、函数特征、过滤逻辑的漏网之鱼,而不是只记 payload。比如看到 preg_replace 就要联想到代码执行,看到 file_get_contents 就要想到文件读取和 SSRF,看到 unserialize 就要考虑反序列化漏洞。这种敏感度只能靠大量阅读源码来积累。
5.2 做笔记的正确姿势:别把笔记写成题解流水账
很多人做笔记就是简单记录"这道题的 flag 是 xxx,payload 是 xxx",那基本等于没写。真正有用的笔记应该回答三个问题:
- 这道题考什么知识点?这个知识点属于哪个大类的哪个分支?
- 我最初为什么没解出来?卡在哪个环节?是知识点盲区,还是工具不熟练,还是没想过这个方向?
- 如果我重新做一次,最短的解法路径是什么?最优 payload 长什么样?
我习惯用 Markdown 维护一个安全笔记仓库,按知识点分类建文件,每道题把思路和 payload 归类进去,这样刷题越久,自己的知识库越厚。等到后面遇到复杂题目,我会先翻自己的笔记,很多时候答案就藏在之前的某一个分类里。
5.3 社区交流:既能找答案,也能找差距
ctfshow 的学习氛围其实很好,平台有社区和群组,不少题目的讨论区里都有非常高质量的思路分享。我的建议是:先独立做,再看讨论区;看完讨论区,再决定要不要看完整题解。
讨论区里除了给出答案,还会有很多人分享"我第一步尝试了什么、为什么失败、最后怎么想到这个方向的",这些过程比结果更有价值。
5.4 坚持的节奏比强度更重要
最后一点其实是心态问题。CTF 学习是一个典型的越学越觉得自己不会的领域。第一天做 Web 入门题可能十道能做八道,到后面可能一道题卡两天。这时候很容易自我怀疑,觉得是不是自己不适合干安全。
我的经验是,把"每天固定刷 1-2 道题"当作最低目标,而不是某一天突然刷 20 道,然后累得两个星期不想碰。以我的个人体验来说,细水长流的节奏,远比集中突击更容易坚持下来。哪怕今天状态不好,只做一道并认真整理了笔记,也是在往前走的。安全这条路很长,保持持续输入比一时热情重要得多。
