☰
CTF Web题实战:信息收集与漏洞利用的Flag挖掘技巧
2026/10/20 5:32:22 网站建设 项目流程

CTF里Web题永远是参赛人数最多、套路也最杂的一个方向。很多新手拿到一道Web题,上来就急着到处点按钮、翻参数,结果折腾半天连Flag的影子都没见到。其实Web题的Flag就藏在两个维度里:一个是信息收集的广度,一个是请求构造的深度。只要把这两条线捋清楚,大部分题目都能在半小时内解决。这篇Writeup我打算把平时打CTF Web题最常用的几招拆开来讲,配合实战中容易踩坑的地方,让刚入门的朋友少走点弯路。

题外话一句:下面提到的所有技巧,只适用于CTF竞赛环境或者自己搭的靶场,千万别拿去对着公网系统乱试。这是底线。

1. 第一层侦查:藏在页面代码与资源文件里的Flag

1.1 先从HTML源码和注释信息查起

很多新手拿到题第一反应是看页面效果,实际上Web题80%的线索都藏在源码里。我见过太多人忽略一个最简单的事实:出题人就怕你找不到Flag,所以往往会用最直白的方式提示你——注释。

某次模拟项目X的题,打开页面只有一行字“Welcome to the challenge”,底部有一张图片。我习惯性地按Ctrl+U看源码,翻到中间看到一段<!-- flag_part_1: ctf{...的注释,然后又发现页脚隐藏着一个<div id="admin" style="display:none">,里面放着一个后台入口。这就是个典型的信息收集题,Flag分成两段,一段在注释里,另一段在后台里,而你唯一要做的是看代码。

源码里常见的信息泄漏点包括:

  • HTML注释:直接写Flag、提示下一个入口、透露后台账号格式。
  • 隐藏表单域:比如<input type="hidden" name="role" value="user">,这种就是典型的越权入口。
  • JS文件里的接口地址:很多出题人会在JS中写/api/getFlag之类的接口名,但不告诉你参数。
  • CSS背景图:极少数题会把Flag编码成图片名字或者background-url的base64参数。

看源码的时候别只盯着当前打开的这一个HTML,右键查看外部引用的CSS和JS文件,逐个点开看,所有前端代码都算页面的一部分。另外火狐和Chrome的开发者工具里,按Ctrl+Shift+F可以直接在所有已加载文件中搜索关键词,全局搜一下flag、ctf{、admin、api,一分钟不到就能找出绝大多数页面级别的线索。

1.2 robots.txt与备份文件的敏感信息泄漏

如果源码里干干净净,下一个要检查的就是站点根目录下面的标准文件。robots.txt在很多CTF题目里就是一个故意留下的提示板,里面有时代码是Disallow: /admin.php,有时候是一段需要解码的字符串。

除了robots.txt,我建议养成一个条件反射式的习惯:访问页面的时候,顺手探测这些路径:

  • .git/目录:一旦存在,整个源码都能用git命令还原出来。实操时可以先git clone整个站,再git log查看提交记录,Flag经常藏在某个历史版本里面。
  • /.svn/、/.hg/目录
  • .bak、.swp、.sav、~后缀文件:比如index.php.bak、flag.php.swp。看到这类文件直接下载,打开就是源码或者Flag。
  • www.zip、web.zip、site.zip之类的压缩包:出题人打包源码的时候忘了清理是很常见的事。
  • phpinfo.php、test.php、info.php

有人会问,怎么知道该探测哪些路径呢?推荐两个办法。一是用开源目录扫描工具扫一下,CTF环境下网站路径不多,几秒钟就出结果;二是根据题目给的提示猜测,如果题面写着“备份文件泄露”或者“源码泄露”,那大概率就在上面这几个路径里。记住一个判断准则:不管用什么工具,扫出来的路径不是重点,重点是你必须逐个访问并分析内容,有些人扫出一堆目录但没耐心打开,等于白扫。

1.3 响应头与隐藏的服务端信息

第三处容易被忽略的信息源是HTTP响应头。服务端返回的每个字段都可能被出题人做了手脚,特别是Server、X-Powered-By、Set-Cookie这些。

实战里我遇到过几种情况:

  • 响应头里直接带着一段base64,解码后是提示或者下一跳路径。
  • Server字段写的是非标准值,比如nginx/1.14.2 (php + flag),这等于明着告诉你后面要用PHP的思路做题。
  • 自定义响应头X-Hint: /backup/,指向源码备份路径。
  • Set-Cookie里admin=0,把它改成admin=1再刷新页面,后台权限就出来了。

看响应头这个习惯要养成到肌肉记忆里。打开开发者工具,切到Network面板,刷新页面,挨个点击请求,看响应信息,也看请求信息。我见过有人Find Flag的时候反复刷新页面死活找不到,其实线索就在加载图片的那个请求的响应头里。如果你用的是命令行方式调试,curl -i、curl -v都可以直接看到完整头信息,比浏览器里点来点去更快。

2. 第二层探查:请求交互中的参数重组

2.1 URL参数与业务逻辑的绕过思路

当页面本身和文件目录都探查完毕,重点就转到请求参数上。Web题最经典的出法就是:后台有个查询功能,你传的参数不同,返回的数据不同,Flag只在特定条件下才会出现在响应中。

这类题的核心是推断服务端代码逻辑。举个例子,某个API是/api/user?id=1,返回普通用户信息,试着把id改成2、3甚至0,一旦某个ID返回了管理员信息,这就是典型的IDOR越权。更进一步,如果题目中传入的id是字母形式的用户名,比如/api/user?name=admin,那就要注意有没有type、role这类辅助参数可以覆盖默认值。

参数绕过的常见策略我整理成一张速查表:

情形尝试方式
数字型参数改为0、1、-1,或者字符串与数字混用
布尔型参数true/false、1/0、yes/no
数组型参数在参数后加[],如id[]=1,有时可绕过弱比较逻辑
同名参数传多个id=1&id=2,不同中间件取值不同
JSON体参数增加冗余字段或用数组覆盖原字段

很多新手容易在这犯一个毛病:看到参数就疯狂改,但改完不观察响应变化。正确做法是每次改一个参数,对比前后响应差异,响应长度、状态码、页面标题都值得记录。比如某个题目传入page=about正常返回,传入page=admin就302跳转到登录页,那说明后端对名称有匹配关系,接下来就该考虑路径穿越或者文件读取。

2.2 Cookie与Session的伪造逻辑

Cookie操作是另一个高频考点,而且很多题出的特别直白。常见的类型有两种:

第一种是可见字段篡改。Cookie里直接放着user=guest、role=user、isAdmin=false,把值改成admin和true再发请求,Flag就到手了。这种题考验的不是技术,是细心。

第二种是签名类Cookie。有些题会给你一个形如session=eyJ1c2VyIjoiYWRtaW4ifQ.x7y8z9的值,前面那段像乱码的其实是base64编码的JSON。先用base64 -d解码看看内容能不能改,再看后面那段签名算法。如果题目没给你密钥,强行改内容大概率会失效;但如果出题人用的是常见的弱密钥,配合工具直接爆破出密钥,再重新签一个并不难。

还有个容易忽略的细节是Cookie的作用域。有些题Flag登录后能看见,但登录用的是子域名下的Cookie,主站读不到。这时候要检查Cookie的Path和Domain属性,必要时手动在开发者工具里新建一个同名的Cookie到正确路径下再访问。这类问题很小,但卡住很多人。

2.3 HTTP请求方法重置与特殊方法

Web题里还有一类考点,考验的是对HTTP协议本身的理解:同一个路径,用不同的HTTP方法访问,服务端处理逻辑会不一样。

最常见的几个:

  • OPTIONS /:查看服务器允许的请求方法,响应里的Allow头直接告诉你哪些方法可用。
  • PUT /shell.php:服务器允许直接上传文件时,用它传一句话木马。
  • PATCH/TRACE/CONNECT:部分服务框架会对这些方法做额外处理。

某次做某跨平台系统题,页面是一个静态文件服务器,目录里有个flag.txt,但直接访问GET /flag.txt返回403。我试了PUT /flag.txt上传内容,成功覆盖了文件,之后GET /flag.txt就把自己上传的内容返回了。整个题的本质就是考察HTTP方法配置错误。

排查这类题目时,我一般先把请求的Method列出来,逐个访问相同URL,观察状态码差异。一个方法一个方法地试,虽然听起来笨,但往往是一道题最核心的突破口。顺便提醒一句,浏览器地址栏只能发GET请求,要想发其他方法,得靠Burp Suite、Postman或者curl-X参数。

2.4 序列化数据与逻辑校验绕过

稍微进阶一点的题,会在传输数据里加入序列化字符串。典型的标识是形如O:4:"User":1:{s:4:"name";s:5:"admin";}这样的PHP序列化格式,或者直接用JSON格式包裹嵌套对象。

碰到这类传输结构,第一反应应该是:后端有没有对这个反序列化结果做权限校验?比如一个序列化对象里有is_admin字段,默认是false,把它改成true再重新编码发送回去,很可能就绕过登录检查了。

这里要特别注意格式一致性。PHP反序列化对字符串长度要求很严格,s:5:"admin"里面的数字5必须和后面字符数完全一致,多一个少一个都会报错或者导致变量不被解析。改的时候先数清楚字节数,改完再用在线工具或者本地脚本重新生成一遍序列化串,别手搓。

3. 第三层突破:Web漏洞利用的通用打法

3.1 SQL注入的识别与绕过技巧

信息收集和参数试探都做完,还没拿到Flag,那大概率要进入漏洞利用阶段了。Web漏洞的数量很多,但CTF考得最稳定的还是SQL注入、文件包含、命令执行、文件上传这几类,而且出题人通常会把过滤条件设置的比较简单,真正难的是思路。

SQL注入的识别过程其实很有规律。找到一个带参数的请求后,先输入一个单引号',看页面是否报错,或者响应长度是否出现变化;再尝试1 and 1=1和1 and 1=2,对比返回内容差异。如果差异明显,基本可以确定存在注入点。

确认存在注入后,一个比较稳的打法是用order by判断列数,再用union select回显数据。CTF里有一类经典考察点:列数知道,但输出位置有限,比如只显示第一条查询结果。这时候可以用union select里的冲空技巧,让前面查询结果为空,后面注入内容直接回显出来。

过滤绕过是经常遇到的情况,尤其是空格和关键字被替换。几种常用办法:

  • 空格被过滤:用/**/代替空格,或者用%0a、%09这类URL编码字符。
  • select被过滤:尝试大小写混合SeLeCt,或者嵌套写法selselectect,如果后端只替换一次就有机会绕过。
  • 引号被过滤:把字符串转成十六进制,比如admin写作0x61646d696e。
  • =被过滤:用like或者in替代。

还有一种是盲注场景,页面上看不到任何回显数据,只能通过响应是否正常、响应时间长短来判断条件真假。手工试太慢的话,直接用自动化工具跑布尔盲注和时间盲注。跑完拿到数据库名和表名,再顺着去找Flag字段,效率高很多。

3.2 文件包含与命令执行的触发点

文件包含类题目的特征非常明显:URL里经常能看到?page=about.php、?file=./index、?template=default这类参数。它的本质是服务端把参数值拼到了文件路径里面,导致你可以读取任意文件,甚至执行PHP代码。

CTF里最标准的一句话利用方式是PHP伪协议:

?page=php://filter/read=convert.base64-encode/resource=index.php

用这种方式可以把PHP源码以base64形式读出来,然后本地解码审代码,找到下一段线索。还有一种方式是用data://伪协议直接写入PHP代码执行:

?page=data://text/plain,<?php system($_GET['cmd']);?>

这种技巧在一些过滤不严的题里可以直接getshell,拿到flag之后别忘了清理日志和临时文件,保持靶场干净。

命令执行类的题则会在ping、转换工具、日志查看等功能里出现。判断方法是看参数值是否被拼进了系统命令字符串。比如有个参数ip=127.0.0.1,后端代码可能是ping $ip,这时候输入127.0.0.1;ls就能看到目录列表。过滤绕过方面,;、&&、|、反引号、$()可以多种方式组合,被过滤了就用变量拼接、通配符、base64编码等方式拆解。

3.3 文件上传与解析绕过场景

文件上传题的核心是在扩展名和内容检查上做文章。出题人一般会校验后缀名和文件头,但校验的规则往往不完整。

几个常见的上传绕过策略:

  • 改后缀为php5、phtml、pht,如果服务器配置支持这些后缀解析,就能执行。
  • 上传一个内容为图片文件头的PHP文件,绕过文件内容检查。
  • 上传.htaccess文件,把图片后缀解析成PHP。
  • 在文件名中加%00截断,或者加上/.、/让后缀校验失效。
  • 用分号或者双扩展名混淆,比如shell.php.jpg。

上传成功之后,访问路径是另一个坑。有些题上传目录不允许脚本执行,但附件目录可以;有些题上传后文件名被重命名,下载时得去响应包或者目录列表里找真实文件名。实操时拿Burp抓完上传请求,回显里通常会带上访问URL,把那个URL复制下来直接访问,避免自己瞎猜路径。

3.4 弱口令与暴力猜解的正确姿势

还有一种很多人嫌“智商低”但竞赛中很管用的题:弱口令、爆破和猜解。这类题不考验技巧,考验的是字典质量和耐心。

常见账号密码组合就那几对:admin/admin、admin/123456、admin/password,有些题目还会在页面源码注释里留下管理员用户名,那密码就可以用常见弱密码跑一遍。实际操作时可以用Burp的Intruder功能加载一个精简的字典,把请求中账号和密码字段标出来,设置好线程数,几百个密码几秒钟就完成了。

跑完的结果要看响应状态码、响应长度和跳转位置。如果某个密码的响应长度和别的不一样,基本就是成功了。这里建议配置文件时别只盯着200状态码,有些登录成功后用的是302跳转,要跟着跳转过去确认。

4. 实操中容易卡壳的点与排查速查表

4.1 前端看似无输入点的情况

很多新手在遇到一个只有静态页面的题时会想:这题是不是坏了?其实所有Web题都有一个入口,只是入口可能藏在你预料不到的地方。

完全没有输入框的题,入口可能有几种存在形式:

  • 某个按钮绑定了一个onclick事件,触发了一个隐藏的fetch请求。
  • 页面的JS代码里有if(admin){ fetch('/getflag') }这类条件语句,你需要手动在控制台执行相关函数。
  • URL路径本身就是参数,试着改路径的后半段。
  • 浏览器开发工具的Console里可能被写入了提示信息,有些出题人会用心输出日志。

遇到这种情况,我个人的处理顺序是:先看JS文件列表,再在全局搜索中找fetch、ajax、XMLHttpRequest这些关键字,顺藤摸瓜找到接口地址。接着把接口地址直接输入浏览器访问,再看返回数据。很多题到这一步就解出来了。

4.2 请求被重定向或者状态码异常

有时候明明参数传对了,页面却一直302跳转,跳来跳去回到首页。这时候别急着换思路,先看看跳转目标地址。如果跳转到login.php,说明鉴权没过,回头检查Cookie或者Session;如果跳转到index.php?err=1,可能是参数格式不对。

状态码也是一个很好的线索源:

状态码常见含义
200正常返回,看内容
301/302重定向,看Location头
403权限不足,尝试加头或改方法
404路径不对,检查大小写和后缀
500服务端报错,查看响应体错误信息

有些题故意把正确页面做成403,让你以为这条路走不通,实际上加上一个特定的请求头X-Forwarded-For: 127.0.0.1或者Referer就能访问。开发代理或者WAF校验的场景在CTF里出现的概率不低,多试几种头没坏处。

4.3 编码与加解密的常见形态

Flag和提示信息经常以编码形式出现,最常见的几种是base64、十六进制、URL编码和md5。识别方法其实很简单:base64的特征是大小写字母加数字加=结尾;十六进制是0x开头或者只有0-9a-f;URL编码是大量的%号。

解码的时候不要手算,直接找在线工具或者本地命令:

echo "ZmxhZ3t...}" | base64 -d echo "666c6167..." | xxd -r -p

还有一种比较坑的点是二次编码,比如先base64再URL编码,解一层发现还带着%,那就继续解第二层。有些题会故意把编码串放在Cookie、响应头或者图片链接的?src=参数里,专注于请求响应往返的数据,总能看到。

4.4 快速排查速查表

平时打题,我身边会放一张自己整理的排查表,碰到卡壳就按顺序过一遍。也不怕大家笑话,这个表虽然简单,但真的帮我解过好几道卡了几个小时的题。

排查项操作
源码Ctrl+U看HTML,Ctrl+Shift+F全局搜索flag关键字段
目录探测.git、备份文件、常见目录名
响应头检查每一个自定义头
参数改数字、布尔值、类型、搞数组
Cookie检查字段名和值的可篡改性
请求方法尝试GET、POST、PUT、OPTIONS
漏洞利用SQL注入、文件包含、命令执行、上传

顺序上,我始终建议先做前四项,再做后三项,因为前面几项成本低、速度快,很多题目真的就是把Flag直接露在外面。

5. 我在Web题上反复踩过的坑

如果回头总结,我把打CTF Web题最容易犯的三个错误列出来,都是我看到身边朋友包括我自己常犯的。

第一个是只看页面不看流量。尤其是刚入门的时候,觉得开发者工具是给前端工程师用的,其实CTF需求里数据包里的信息比页面渲染后的信息重要得多。以后遇到奇怪的现象,第一反应先打开Network面板重新加载页面,逐个请求检查。

第二个是改参数不保留记录。很多新手在Burp里修改参数,改乱了就忘了原始请求长什么样,最后代码逻辑理不清楚。正确做法是先把原始请求保存下来,每次修改都基于原始数据包,改一条加一行注释,理清哪里试过、哪里没试过。

第三个是不肯主动扫描目录。很多人怕扫描工具动静太大,实际在CTF靶场里完全没这个顾虑。快速扫一下公共目录,拿到路径列表后再手动分析,可以省下一大半试错时间。只要别忘了扫描结果必须人工验证就行。

6. 最后分享一个实操小技巧

也不算压箱底的东西,就是我在一次一次试错里总结出来的:当你确定思路正确但死活拿不到Flag的时候,回去读一遍题面。CTF题目的描述,出题人为了控诉难度或者给提示,喜欢在题面里埋词。比如题面写着“藏在深处的秘密”,“深处”可能就对应目录递归;写着“管理员专属”,那很可能就是越权或者Cookie伪造;写着“只有本地能访问”,那八成需要伪造来源IP。

文本里出现的每一个词都值得想一想是不是技术暗示,这个习惯帮我避开了很多弯路。另外,解出题之后,记得去看看这道题的官方Writeup或者别人写的Writeup,对比自己的解法,一般能学到一两个更巧妙的思路,这也是CTF进步最快的方式。

Web题这东西,难度高低从来不在工具,而在于你建模的思路:信息收集做到什么程度,参数分析得够不够细,漏洞利用的判断准不准。多练几道题,把这套流程变成肌肉记忆,你也能做到看见页面就知道下一步该干什么。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询