如果你也在刷Web方向的CTF题,那么 buuctf-web-wp 这套WP应该能帮你少走不少弯路。它本质上不是一篇题解,而是一个持续维护的个人解题记录库:把我在某个常见线上CTF靶场上刷过的Web题目,按照漏洞类型、出题思路、利用链、踩坑点重新组织成了一本随时可以翻的小手册。
这个项目解决的痛点很具体:刷题当时觉得自己懂了,隔两周再看笔记,只看到一行命令,完全想不起来为什么这样打。所以这套WP的核心不只是记录“怎么拿到flag”,而是记录“看到什么特征会往哪个方向想”,让每一道题都变成一类题的缩影。它适合刚入门Web安全的CTF选手,也适合那些刷了不少题、但总觉得知识点散成一盘沙的学习者。
下面我会把这套WP从骨架设计、考点拆解到实操链路完整讲一遍,都是我自己维护过程中真实沉淀下来的方法。
1. 项目概述:为什么会沉淀这份Web题解手册
1.1 这个项目到底解决了什么
Web方向的CTF题有个特点:题型固定,但变种极多。SQL注入、文件包含、反序列化、命令执行、SSTI、SSRF、XXE,翻来覆去就那么几十类,但每道题都会在过滤、解析差异、逻辑层级上加一点自己的东西。如果只是刷题不沉淀,很容易陷入“这道题会了,下道变体又不会”的死循环。
buuctf-web-wp 想解决的就是这个记忆断层。它把每次做题的关键路径拆成四个部分:信息收集阶段看到了什么、漏洞点为什么从这个特征切入、利用过程哪些参数是绕过关键、最后flag格式和整体利用链是什么。这四个部分一旦固定下来,复盘时就能很快重建当时的思考现场,甚至能对照出自己经常在哪个环节卡壳。
另一个很实际的场景是查资料。以前遇到一个陌生考点,要在浏览器里翻各种零散博文,而现在直接在本仓库里按标签搜索,就能找到以前记录过的同类题目和对应绕过技巧。这种“自己的武器库”的感觉,比临时抱佛脚刷搜索引擎要踏实很多。
1.2 适合谁参考,怎么用效果最好
如果你刚接触Web安全,这套WP可以作为题型地图来用。先按目录找到漏洞大类,看每道题的信息收集特征和判断流程,再回到题目环境里自己动手复现一遍。不建议直接对着WP里的payload照抄,那样只会得到flag,得不到思路。
如果你的目标是准备校招或渗透测试岗位面试,可以把这套WP里的“题目类型聚合”部分当知识清单。比如看到“文件上传”就想到检查内容类型、扩展名、二次渲染、.htaccess、解析漏洞,这些从题目里提炼出来的点,比背面试题更牢固。
我自己的使用习惯是每周固定刷三到五道题,刷完当天熬夜把WP更新进去。时间久了以后,它就不再是单纯的解题记录,而是一本反映自己能力成长轨迹的笔记。回头翻半年前的记录,会发现当时认为很难的利用链现在一眼就能看穿,这种正反馈是坚持维护的最大动力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 题解合集的骨架设计:不再是一堆杂乱笔记
2.1 按题目类型聚合,而不是按时间顺序
很多人记WP的习惯是刷一道写一篇,最后文件夹里躺着几百个零散文件,想找类似题的时候根本无从下手。我在维护 buuctf-web-wp 的过程里做过一次大重构,核心变化就是目录结构从“按时间”改成“按类型”。
目录大致长这样:根目录下先按漏洞大类拆文件夹,比如 sql-injection、file-inclusion、rce、deserialization、info-disclosure;大类下面再按具体技巧细分,比如 sql-injection 里分成 union-based、error-based、blind-based、stacked-injection、no-filter-bypass 等。这样做最直接的好处是,以后遇到一道新题,心里会有一个映射过程:这题特征属于哪个目录,和以前哪道题类似,直接去翻对应文件就能找到参考思路。
这个设计也暗合了出题人的思路。出题人设计题目时,通常会选一个攻击面,然后在某个环节设置过滤或逻辑陷阱。按类型归档,等于你提前把攻击面地图铺开了,做题时不是从零开始想,而是从已有的地图里匹配最接近的路线。
2.2 每道题固定模板:题干摘要、信息收集、绕过点、利用链、Flag格式
归档结构确定后,每道题的内容也要有统一模板。没有模板的后果是:状态好的时候写得很详细,状态差的时候只写一行 flag,过一个月自己都看不懂。我后来固定了五段式模板,每道题不管难易都按这个结构写。
第一段是题干摘要,记录题目给的入口和提示信息,比如“一个登录页面,提示有备份文件”“一个留言板,过滤了关键词”。第二段是信息收集,写下访问后的首页状态、URL特征、响应头、目录扫描结果、源码或注释里泄露的信息。第三段是绕过点,专门记录过滤规则是什么、怎么探出来的、选用哪种方式绕过的。第四段是利用链,把从漏洞发现到最终读取flag的完整路径按步骤写清楚。第五段是Flag格式和本题的总结一句话,这句话会提炼成搜索标签。
用模板之后还有一个额外收获:写WP的时间肉眼可见地变短了。因为结构固定,不用每次想怎么开头怎么结尾,只需要往对应的段落里填内容,大脑的决策负担小了很多。
2.3 为知识点建索引,让一道题变成一类题
五段式模板解决了单题记录完整性的问题,但不能解决跨题知识的聚合问题。所以我在仓库里单独维护了一个 INDEX.md,相当于整本手册的知识索引表。每条记录包含知识点名称、出现过的题目文件链接、关键参数或载荷、链接到哪个更细的子文档。
举个例子,php伪协议 这个知识点会在 file-inclusion、file-read、rce 等多道题里出现。以前需要翻三个文件才能找到不同用法,现在索引表里一行就能看到每个用法的题目位置。更进一步,我会把同一知识点的不同绕过方式做成对照表,比如读取文件分别可以用 php://filter、data://、php://input,什么场景下用哪种,表中一目了然。
这个索引的维护成本并不高,每次写完一道题花两分钟更新一下对应行就行。但它带来的收益很大,从“我记得好像做过类似题”变成“我知道知识点在哪里,直接跳过去看”。当题目数量积累到两三百道以后,有没有这套索引,使用体验完全是两个档次。
3. 核心通关技巧:Web方向的高频考点拆解
3.1 SQL注入:从字符型到报错到堆叠的判定顺序
SQL注入是Web方向绕不开的基础考点,buuctf-web-wp 里这类题目最多,变种也最杂。我的记录方式不是每个payload都记一遍,而是记下一套固定的判定顺序,这样遇到新题能快速定位注入类型。
第一步永远是判断注入点类型:数字型还是字符型。用单引号加注释符看报错,再尝试 1' and '1'='1 与 1' and '1'='2 的页面差异。第二步判断当前数据库版本和权限。版本不同,后续利用方式完全不同,比如MySQL 5.0以上可以直接查 information_schema,低版本则可能需要暴力猜解。第三步是根据回显情况选择注入方式:有直接回显的走Union注入,无回显但能看页面变化的走盲注,报错信息能带出查询结果的走报错注入。
关于绕过技巧,我特意在WP里单独归纳了一个“过滤绕过速查表”。过滤了空格就用注释符 /**/ 或括号;过滤了关键字就用大小写混合、双写或者字符串拼接;过滤了 = 就用 like、rlike、in 替代。这些不是背下来的,而是从一道道题目里试错试出来的,写进WP后再遇到同类型过滤,基本能秒出方案。
还有一点容易被忽略:堆叠注入。很多人都知道 ; 能隔开多条语句,但很多题目的查询函数只允许执行一条语句,所以堆叠注入能不能用,必须实际测过才能下结论。我的经验是先试 1';show tables;--+这类简单探测,如果没返回错误,再往上堆叠更复杂的语句,如果报错,说明数据库连接层把多条语句拦掉了,赶紧换其他注入方式。
3.2 文件包含与伪协议:一个最容易被忽略的入口
文件包含漏洞在Web题目里出现频率极高,但很多人一看到 include 函数就直接套伪协议,忽略了先判断包含路径可控范围这个前提。我在WP里专门开了一个章节记录这类题的判断思路。
拿到一个包含点,第一步看参数是直接拼进路径,还是经过了路径过滤。如果参数原样拼入,先试相对路径和绝对路径读系统文件,同时观察报错信息里是否透露了当前目录位置。第二步才是尝试伪协议:读源码用 php://filter,执行代码用 php://input 上传PHP代码,读目录和文件用 data:// 构造内容。这里有个细节很多人踩坑:php://filter 的 read=convert.base64-encode/resource=xxx 读出来的内容是一坨base64,必须解码才能看到原始代码,解码之后才能分析源码里有没有更多利用点。
还有一个容易忽略的点是文件包含配合 zip:// 或 phar:// 协议。这类题目通常要求先上传一个恶意文件,再通过包含协议触发执行。判断方法很简单:如果题目给了文件上传功能,又有文件包含点,两者结合就极大概率是这条路。我的记录习惯是把这类题单独归到“包含与上传组合利用”目录,因为它的解题链路和纯文件包含完全不同。
3.3 代码执行与命令执行:找到那个过滤盲区
代码执行和命令执行类题目,核心考验的不是你背了多少函数,而是你能不能快速找到过滤规则的盲区。记录这类WP时,我要求自己至少写清楚三个点:输入点在哪、过滤了什么、为什么这个绕过方式有效。
常见的代码执行绕过思路是拼接和变形。过滤了 system,可以用 sys"tem" 或 system 加注释符拼接;过滤了括号,可以考虑 include 或 require 等不需要括号的调用方式;过滤了字符串,可以用变量函数或数组方式实现动态调用。这些绕过技巧单独记一条没有意义,必须对应到具体题目的过滤规则里,才能体现“找盲区”的思路。
命令执行的过滤盲区则更多体现在空白符、连接符、关键字处理上。空格被过滤可以用 <、${IFS}、%09 代替;分号被过滤可以用换行符代替;关键字被过滤可以用环境变量读取或者 $(expr) 拼接。每次做这类题,我都会在WP里额外记录一个问题:这个绕过方式是普适的还是只对这题的过滤规则有效?这样才能避免把特殊解法硬套到另一道题上。
3.4 信息泄露与备份文件:比漏洞更早出现的突破口
很多时候Web题不需要复杂的漏洞利用,信息泄露本身就是入口。buuctf-web-wp 里专门有一个“信息收集与泄露”分类,收录了大量通过源码注释、备份文件、目录列表、日志文件拿flag的题目。
这类题的流程非常固定:优先扫目录,重点关注常见备份后缀,如 .bak、.swp、.zip、.git;访问管理入口和报错页面;看源码注释里的提示;尝试直接访问常见敏感路径。我把常见的扫描字典整理成了一份自己的清单,在指数级提高效率的同时也大大减少了漏扫概率。
最值得记录的是那些“非标准信息泄露”题。比如某个题目把备份文件放在了一个很难猜的目录里,但页面源码的JavaScript里泄露了目录线索;或者登录接口返回了详细的SQL报错信息,能直接拼接出库名和表名。这类题的共同点是:信息就在那里,关键在于你有没有看全。我在WP里会专门用一段“本题信息收集亮点”来复盘这类非标准入口,这样以后再看类似页面时,会自然形成多留一个心眼的习惯。
4. 实操过程:从信息收集到拿到Flag的一条完整链路
4.1 建立标准信息收集SOP
做题这么多年,我最大的体会是:信息收集不是碰运气,而是一套可以固化的流程。在 buuctf-web-wp 里,我把我自己的信息收集流程沉淀成了一个SOP,每道题的第一步都是执行这套流程,而不是先猜漏洞点。
这套SOP大致是这样:先看题目描述里有没有提示,很多题目的考点就直接写在描述里了;然后访问页面本体,打开开发者工具看网络请求、Cookie、响应头、源码注释;再重点看JavaScript文件,里面经常藏着接口地址和敏感参数;最后做一次目录扫描,把常见路径字典跑一遍。做完这四步,题目的攻击面基本就能框出来了。
也就是说,跳过信息收集直接找漏洞是新手最常见的错误。你以为自己在省时间,实际是在拼运气。信息收集做得扎实,后面每一步都有据可循,连试错都有方向。我在WP里为每道题记录信息收集结果,就是为了让这个习惯变成每次做题的肌肉记忆。
4.2 一次典型题目的完整复现过程
这里用一个去标识化的模拟题目来展示整套解题链路。题目入口是一个普通的搜索框,提交内容后页面会显示搜索结果条目数。我先按SOP过一遍:首页没有注释泄露,响应头正常,目录扫描发现存在 robots.txt,里面写着两条记录:一条是搜索页面,另一条是后台登录路径。
访问后台登录路径,发现是一个POST表单。我先用弱口令跑了几组常见账号密码,无果。查看网络请求,发现登录接口是 /admin/login.php,响应里带有SQL报错信息。凭借这个特征,我判断后台查询语句直接把用户名拼接进去了,于是走SQL注入流程。用单引号测试发现闭合成功,继续用 order by 逐列探测,猜到查询字段数为3,然后是用Union注入读出数据库名、表名和字段名,进而读管理员密码哈希。
拿到密码哈希后,用在线破解工具解出明文(题目用的是弱口令哈希,强度很低),登录后台,发现后台有一个上传点。上传一个带PHP代码的文件被拦截,提示只允许图片格式。这里进入文件上传与解析漏洞考点。我尝试上传图片马配合文件包含点,但该题目没有文件包含功能。改用双写扩展名、大小写绕过、加空格绕过,最终在一个很冷门的后缀变体上突破了校验。
上传成功之后,访问上传目录拿到shell,然后在当前目录查找flag文件并读取。整个过程从信息收集到最终拿flag,大概用了四十分钟。我把每个断点的判断依据都写进了WP:看到SQL报错时为什么直接确认注入,上传拦截时为什么优先试扩展名绕过,这些比结果本身更有参考价值。
4.3 记录利用过程的节奏:什么时候该截图,什么时候该写命令
写WP不是把所有内容一字不差地贴上去,而是要掌握记录的节奏。我的原则是:能让读者直接复现的步骤必须写清参数和命令,但重复性的试错过程只要总结成一句话就够了。
比如SQL注入里盲注脚本的完整代码值得贴,但中间跑了几次字典猜出表名这个过程,只需要写“用二分法脚本跑了几分钟,得到表名 admin_user”就可以。又比如文件上传题,被拦截的尝试过程不用录屏,但成功绕过的那种载荷必须记完整。截图也一样,只有能体现“这里有个特征导致我判断漏洞类型”的截图才值得保留,纯粹的已知界面截图没必要。
还有一点是关于payload的版本管理。同一个绕过可能有好几个变种,有的能在当前环境跑通,有的不能,我会把跑通的payload标记为“本题可用”,同时备注适用条件。这样以后其他题目有类似环境时,能直接判断这个payload是否值得先试。这类细节不写进WP的话,过几个月再看,你根本记不清当时是怎么试成功的。
5. 做WP时最容易踩的坑与排查思路
5.1 环境差异:本地复现不了就回到题目环境里测
维护这套WP的过程中,我踩过最大的坑就是本地环境复现和题目环境不一致。某道题在远程靶场里能跑的payload,本地搭的同版本环境却死活跑不通,写了半天WP,结论却不可靠。
后来我把排查顺序改成:先在题目环境里用payload验证一遍,拿到flag后再选择性地本地复现。如果本地复现不了,我不会停下来一直纠结,而是在WP里注明“本题利用依赖目标环境,本地复现未成功”这个限制条件。这样做的好处是,WP的结论永远以题目环境为准,不会因为本地环境差异导致记录失真。
环境差异带来的另一个启发是:复现题目本身也是一项重要技能。有些题需要特殊配置,比如特定PHP版本、特定中间件解析规则,只有把这三个要素都还原,才能完整跑通利用链。我现在每道题都会把环境特征一并记下来,下次要用的时候不用重猜。
5.2 只看结论不看过程:WP里最该写清楚的是“怎么想到这个点”
很多人在写WP时习惯只写“用这个payload就拿到flag了”,完全跳过为什么想到用这个payload。这样写出来的WP,除了证明你会抄答案,对能力提升毫无帮助。
我的记录方法是在每个关键节点加一句“判断依据”。比如“页面源码里看到 id=xxx 直接拼进SQL语句,因此优先试SQL注入”“上传返回的报错信息提到 MIME type 不允许,因此先检查Content-Type绕过”“反序列化题的Cookie格式里出现了 O:4:"User" 字样,因此先尝试构造序列化字符串”。这些判断依据才是复盘的核心价值,因为下次遇到类似特征时,你会条件反射地想到对应攻击方向。
如果某个点你根本想不起来当时是怎么想到的,那就在WP里标注“本题此处存疑”,等以后再看到时补充。坦诚记录自己的不确定,比假装每一步都思路清晰要有用得多。
5.3 依赖工具成瘾:什么时候该手动,什么时候该用脚本
工具能大幅提升效率,但也容易掩盖理解漏洞本质的机会。我在 buuctf-web-wp 里专门写了一节“手动/工具使用边界”,用来提醒自己和读者哪些环节不能纯靠工具。
比如SQL注入,如果环境允许用自动化工具一把梭,确实很快,但很多题目做了过滤,工具直接跑不动,这时必须手动调整参数。所以我的经验是:先用工具快速探测是否存在注入,确认存在后,手动分析闭合方式,再决定用工具还是写脚本。盲注场景推荐写脚本,因为涉及大量请求,手点不现实,但脚本里的判断逻辑必须自己写清楚,这样才能在工具失效时还能手动跟进。
工具选择也有讲究。目录扫描可以用常见的字典工具,但字典质量决定了覆盖率,我会把自己的字典和题目特征结合,不断补充新想起来的路径。流量查看工具、请求改包工具、浏览器开发者工具各有用处,但最核心的还是脑子里的分析思路——工具只是手臂的延伸,不能替代判断。
6. 这套WP的后续扩展方向
6.1 从WP库升级为知识库
做了几十道题以后,我发现单纯按题目归档还是不够,同一个知识点散落在多个文件里,时间一长仍然容易遗漏。于是我开始在 buuctf-web-wp 的基础上做知识库化:把分散在题目里的知识点提取出来,写成独立文档,然后在题目文件里用链接关联到对应的知识点。
比如反序列化这个方向,我会单独维护一份 PHP反序列化知识基础 文档,内容包括魔术方法触发条件、pop链的构造思路、常见框架利用链分析。每做一道相关题目,就在这份文档里补充新的触发点和利用链。这样题库里的每一道题知识条目都指向这份统一文档,看题时能顺着链接跳到知识主干,看知识主干时能反向找到对应实战题目。
这个改造的本质是把“题目驱动”变成“知识驱动”。题目数量再多也只是载体,真正沉淀下来的是可迁移的攻击思路。这是我觉得这套WP未来最有价值的方向。
6.2 建立自动化索引和标签体系
随着文件数量增加,手工维护 INDEX.md 开始变得麻烦。我后期写了一个简单的本地脚本,自动扫描各题文件头部的元信息,生成标签索引。每道题在开头会写一段 tags: 字段,脚本收集所有标签后自动生成最新索引。
标签设计也要讲究,不能每道题都打七八个标签,那样等于没打。我一般控制在四个以内:主标签是漏洞类型,副标签是具体利用技巧,还有一个标签是题目难点关键词。比如一道题是“基于时间盲注的SQL注入,难点在绕过正则过滤”,标签就是 SQL注入、时间盲注、正则绕过。这样搜索时能很快过滤到同类技巧,还能统计自己最常卡在哪类难点上。
脚本本身不复杂,核心价值在于解放了手工维护索引的负担。从此每次更新完WP,跑一遍脚本,索引自动刷新,这种“写题五分钟、整理两小时”的尴尬感就消失了。
6.3 把解题思路沉淀成适合自己的检查单
最后建议把WP里的经验凝练成几张检查单,做题和面试都能用。检查单不是背题,而是把高频判断逻辑压缩成可执行的步骤。
比如我有一张“Web方向第一轮检查单”:信息收集阶段看描述、源码、JS、响应头、目录扫描、robots;判断漏洞类型阶段看参数位置、过滤规则、反馈方式;利用阶段看闭合方式、可读回显、文件上传点、包含点。做题时拿着这张单子过一遍,基本能覆盖80%的常见考点。这套检查单不是一次性写成的,而是每做一道新题,发现遗漏了就补一个条目,慢慢迭代出来的。
这个项目维护到现在,我最大的感受是:记录本身也是一种能力积累。那些当时觉得“没什么好写”的题目,后来往往成为解决同类题目的关键参考。如果你也在刷Web题,建议你从今天开始维护自己的WP库,不用一开始就追求完美,固定模板、坚持记录、持续迭代,它会成为你技术成长路上最忠实的伙伴。
最后再分享一个小技巧:在每道题的WP末尾,加一行“这道题如果换个方式出题,我可能会在哪个环节增加难度”。每次做这种假想,都会倒逼自己把漏洞本质再想深一层,这些写在纸面上的推演,往往比题目本身更能提升你的攻击思维。
