ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CTF信息收集实战指南:从被动侦查到源码泄露的完整方法论

CTF信息收集实战指南:从被动侦查到源码泄露的完整方法论

大家刚开始打CTF的时候,可能都经历过这个阶段:好不容易拿下一道Web题或者渗透靶机的入口,结果发现自己根本不知道下一步该干什么。网上搜了一堆工具,nmap、dirsearch、Burp Suite全都装了,对着目标一顿扫,结果拿到的信息乱七八糟,入口没找着,反而把自己搞懵了。

我当时也是这么过来的。后来经验多了才明白,CTF里的大部分问题都不是工具不够强,而是信息收集的思路没建立起来。尤其是Web题、渗透题、综合题,信息收集的深度直接决定你能不能找到那个藏在角落的flag。把题目给你,第一件事不是急着上扫描器,而是先想明白“这台机器上可能有哪几类东西”,再根据这个判断决定用什么姿势去收集。

这篇分享我打算把CTF里最常见的信息收集套路完整捋一遍,包含被动收集、主动扫描、源码泄露利用、敏感文件挖掘这些环节,配上自己实战中觉得好用的工具和参数,也会讲一些踩过的坑。无论是刚入门的新手,还是已经打过几场比赛但效率不高的朋友,我觉得多少都能有点收获。

1. 信息收集不是“扫描”,是建立攻击地图

1.1 先想清楚要什么,再决定怎么收

CTF里的信息收集,本质上和现实中去陌生小区找人是一回事。你不会拿着大喇叭满小区乱喊,而是会先看看门牌号、观察一下哪几栋楼亮着灯、问下门卫这家住几楼,心里有个地图再行动。

放到题目里也是这样。你先要搞清楚目标是什么形态:

  • 是只看一个IP,还是要从一个域名开始往深处挖?
  • 是明文HTTP服务,还是HTTPS后面还有一层框架?
  • 页面本身是一个登录框、一个文件上传点、还是一个目录展示页?
  • 对方是常见的开源CMS,还是纯手写的接口服务?

这些问题,在动手之前就该有一个大致假设。有了假设,才能决定用哪一类工具、跑哪一类字典、重点翻哪几个目录。盲目扫描最大的问题是,你会得到一大堆结果,但根本没有优先级,最后把所有时间都浪费在无效信息上。

我的习惯是,把信息收集分成“先被动、再主动、后利用”三个阶段。被动阶段只看公开信息,不直接碰目标;主动阶段才开始发请求,探测端口和路径;利用阶段是把收集到的线索串起来,找到真正的漏洞入口。

很多新手上来就直接端口扫描加目录爆破,等于跳过了被动阶段,也跳过了对目标的理解,这样效率其实很低。

1.2 被动收集与主动收集:两条腿走路

被动信息收集,指的是不与目标系统产生直接交互的情报获取方式。比如查备案信息、Whois、DNS记录、证书透明度日志、网页存档、代码搜索平台等等。这些数据在公网上本来就存在,目标并不知道有人在看它,隐蔽性很好,拿到的东西也往往是主动扫描得不到的。

主动信息收集则相反,像端口扫描、目录枚举、指纹识别、服务版本探测,都是直接向目标发请求,然后根据响应来判断对方是什么、开了什么、藏了什么。速度快、信息量大,缺点是动静太大,容易触发日志告警,甚至有防护系统会直接拦掉你的IP。

两者怎么配合?我通常的做法是:先用被动手段把目标的家底摸一遍,比如有哪些子域名、哪些端口曾经开放过、用了什么框架、有没有历史遗留的备份文件线索。有了这些铺垫,再用主动扫描去验证和补充。

顺序反过来的话,你可能扫到一半IP被封了,结果还没拿到什么有价值的情报,那就很被动了。

2. 被动信息收集:不用碰目标也能拿到的线索

2.1 网络测绘与搜索引擎:先把目标底牌摸清楚

被动收集的第一步,我建议先上网络测绘平台。现在互联网上有很多公开的资产测绘平台,比如FOFA、Quake这类,它们会把全网IP的端口、服务指纹、标题、证书信息都记录下来。你只需要输入目标的IP或者域名,就能看到这个目标在公网暴露了哪些服务,这比你自己nmap去扫要快得多,而且很多情况下不会被目标的防护拦截。

用法其实很简单。假设你拿到的目标是example.com,你可以直接在测绘平台里搜索域名相关的资产,看它绑定了哪些IP、哪些端口。在CTF环境里,目标通常是一个独立IP,搜索该IP的结果大概率就是这台机器开了哪些服务。这时候你就能发现,哦,原来这个IP不只开了80端口,还有5000端口,那5000端口上跑的没准就是一个脆弱的服务,这条线索直接决定了你后续主攻方向。

我自己在测绘平台上比较喜欢看的字段有三个:端口、服务指纹、页面标题。页面标题有时候会直接暴露后台管理系统、测试环境、或者某些客户端的名称,这些信息单凭主动扫描不一定会浮出来。

搜索引擎也不能忽略。这里说的不只是通用搜索引擎,而是针对代码的搜索方式,比如GitHub的代码搜索。CTF题目经常有开发者把源码传到公开代码仓库,结果没设好权限,这种信息一旦搜到,等于题目已经白送一半了。搜的时候可以用目标的域名、特殊路径、或者一些代码特征作为关键词。

2.2 证书痕迹、网页存档与DNS记录:三个容易漏的信息源

先说证书透明度日志。如果目标网站启用了HTTPS,那么它申请证书的记录都是公开可查的,查询这类日志的典型入口是crt.sh,输入域名就能列出该域名相关的所有证书申请记录。证书的申请记录里常常包含子域名,比如你只知道example.com,查出来却发现还有dev.example.com、test.example.com这些子域名,那这些子域名各自都可能是一个独立的题目入口。

网页存档同样值得翻。存档服务会定期抓取目标网站的快照,你可以看到这个网站在过去几个月甚至几年里长什么样。很多开发者在项目上线早期会把测试页面、备份文件、甚至带有密码的配置文件放在公开目录下,后来虽然删了或者改了,但存档里可能还留着快照。你顺着这些历史URL去访问,有可能直接命中一个遗留的漏洞入口。我在比赛中靠这招翻到过不少后台地址,原理就是旧版本页面里有指向后台的链接。

DNS记录也不能只看A记录。SPF记录、DMARC记录、MX记录这些信息,有时候会无意中暴露目标使用的第三方服务商或服务器IP。举个例子,如果目标的MX记录指向某个邮件服务器IP,而这个IP和主站IP不在同一网段,那这台邮件服务器就可能是一个独立的信息系统,多一个入口就多一分机会。CTF综合题里,这种“域外资产”往往是出题人故意埋的点。

2.3 指纹先行判断:让后续扫描有的放矢

被动收集的最后一环,我建议做一次技术栈指纹确认。这一步可以在浏览器的隐身模式里手动访问目标,看看响应头里暴露了什么信息,比如Server: nginx/1.18.0、X-Powered-By: PHP/7.4、Set-Cookie里的会话名称等。这些头字段会告诉你对方是Nginx还是Apache、语言是PHP还是Java还是Python,框架是哪一家的。

还有一种更省事的方式,就是用浏览器插件,比如Wappalyzer,访问页面时它会自动帮你识别CMS、框架、JS库、Web服务器等。识别出来的结果可以直接用来网搜这个框架有没有已知漏洞,尤其是在目标站点用的是开源CMS的情况下,找到版本号基本就等于找到了漏洞库里的目标。

指纹信息收集得越准确,后续主动扫描的方向就越清晰。如果确定是ThinkPHP,就重点找对应版本的RCE利用;如果确定是某个Java中间件,就去搜它的反序列化漏洞。很多人扫描浪费时间的根本原因,就是在没确认指纹的情况下,眉毛胡子一把抓。

这一阶段做扎实之后,你已经相当于把目标的地图画出了一半,剩下的就是用主动手段去验证和细化。

3. 主动信息收集:端口、目录、指纹的实战打法

3.1 端口扫描:全端口加版本探测,别只扫80

主动收集轮到端口扫描了。这里我先说一个最常踩的坑:很多人习惯直接用nmap默认扫描,只扫常用端口列表,这就可能漏掉题目故意开的高位端口。

CTF的题目环境里,服务经常不是只开在80或者443上的。我见过不少题目在8080、8888、5000、60000这类端口上开了后台接口、管理面板、或者另一个业务系统。你要是只扫了默认端口,就算目标页面好端端放在5000端口上,你也看不见,题目直接卡死。

所以我的建议是,CTF里端口扫描直接用全端口模式:

nmap -sS -sV -p- --min-rate 2000 目标IP

解释一下这几个参数的含义:

  • -sS:SYN半开扫描,快且不容易被应用层日志记录,大多数场景下够用。
  • -sV:探测端口对应的服务版本,信息收集的关键一步,拿到版本号才能去匹配漏洞。
  • -p-:扫描全部65535个端口,别省这一步。
  • --min-rate:最低发送速率,设为2000是为了快速过一遍端口列表,比赛不等人。

全端口扫完,你会得到一个端口开放列表。这时候别急着高兴,把所有跑着HTTP服务的端口都自己在浏览器里打开看一眼。有些端口虽然开着,但不是Web服务,比如可能是SSH、Redis、MySQL,这类服务本身可能就是出题点,尤其像Redis未授权这种经典考点,端口一开就是送分题。

另外,扫描结果里显示的端口服务版本如果比较明确,可以直接去搜对应版本漏洞,比如某个老版本Nginx存在解析漏洞,某些版本的OpenSSH有用户名枚举风险。这里要提醒一下,扫描只是起点,不要寄希望于一次扫描解决所有问题。

3.2 目录枚举:字典、线程与后缀组合的经验值

端口确认了,Web服务也开了,接下来就是翻目录。目录枚举这一步,工具我比较常用的是dirsearch和gobuster。

dirsearch胜在开箱即用,自带字典比较全,你只要给定URL就能开始跑;gobuster则更灵活,支持各种模式的暴力破解,适合自己控制字典和线程。ffuf我也用过,尤其适合做参数和接口的模糊测试,灵活性和性能都很不错,但对字典的要求也更高。

这里单独说一下线程参数。很多人觉得线程开得越大越快,真实情况是大线程很容易触发服务器的并发限制,或者直接被WAF拦下来。常见做法是控制在20到50之间,如果目标明显反应变慢或者开始返回429状态码,马上降速。

后缀枚举也是关键。拿dirsearch举例,你可以指定多个扩展名,比如同时找.php、.html、.bak、.zip、.sql、.txt、.swp:

dirsearch -u http://目标IP -e php,html,bak,zip,sql,txt,swp -t 30

CTF里目录扫描最值钱的命中也集中在备份文件、源码文件、敏感配置文件这几类上。z压缩包、sql数据库备份、swp编辑器交换文件,任意命中一个,都可能是一整个源码泄露的入口。所以我通常不满足于默认字典跑一轮,跑完默认字典之后,还会再用自己的CTF专项字典补一轮,重点找admin、backup、test、upload、flag、login这些关键词路径。

3.3 指纹识别确认:拿到框架版本就成功一半

目录扫描的同时,我一般会顺手做一次更细的指纹确认。这一步不是简单看返回头,而是去访问几个框架特有的路径。

如果你的扫描结果里出现了/wp-login.php,那基本能确定是WordPress,接下来就去查这个WordPress版本的已知漏洞。如果页面里出现了/ThinkPHP特有的报错页面、或者在/index.php后面加特定参数能触发异常输出,那很可能就是ThinkPHP站,赶紧翻漏洞库找对应版本的RCE链。

很多开源CMS、开源商城系统,它们的登录后台路径、API接口路径、甚至安装残留文件都是固定不变的。这些路径本身就是最好的指纹来源。访问一下/administrator、/manager、/console、/api这类常见路径,看返回状态码和页面内容,就能帮你把目标的身份彻底坐实。

指纹确认完之后,关于这个目标“是什么、跑在哪、有没有漏”这三个问题,你已经有很明确的答案了。接下来做的所有利用尝试,都会在这张信息地图上按图索骥,不会再对着空气开枪。

4. 源码泄露与敏感文件:最容易翻出分的地方

4.1 .git、.svn与备份文件:开发者的“后门”

目录扫描命中了一堆高价值文件之后,真正的重头戏开始了。CTF里最经常出现的几类源码泄露,我挨个说。

首先是.git泄露。原理其实很简单:开发者用Git管理代码时,项目根目录下会生成一个.git目录,里面保存着每一次提交的完整记录和文件快照。运维如果直接把项目目录发布到Web服务器上,而忘了限制.git目录的访问,那任何能上网的人都可以通过访问http://目标/.git/把整个代码仓库历史扒下来。

我见过不少新手直接访问/.git/config发现能读到内容,然后就开始手工下载,结果下载半天不知道下一步怎么办。正确做法是用现成的工具,比如GitHack这类,它会自动解析.git/目录的索引,把能恢复的文件全部拉下来,然后你在本地就能看到完整的项目源码。

python githack.py http://目标/.git/

跑完之后,你本地就会多出一个项目目录。接下来就舒服了,直接去看配置文件的数据库账号密码、看源码里有没有注释掉的密钥、看路由文件里有没有隐藏接口。很多时候flag根本不在漏洞利用里,而是直接写死在源码的某个文件里,这种题就是纯考信息收集。

其次是.svn泄露,原理类似。SVN在项目目录下会留下.svn目录,里面保存了版本信息和部分文件文本,旧版本SVN甚至可以直接通过.svn/entries文件读取目录下的文件列表。虽然现在用SVN的项目少了,但挨打的老系统里偶尔还能碰上。

还有一类更粗暴的,就是备份文件泄露。开发者在更新代码前总喜欢打包一份,比如www.zip、backup.zip、site.tar.gz、index.php.bak,打包完放到服务器上忘删了。这种文件一旦被目录扫描器命中,直接下载解压就是整个网站源码。所以我的字典里这类后缀和文件名是重点照顾对象。

4.2 页面源码、JS文件与注释:细节里藏考点

除了这些文件层面的泄露,还有很多信息根本不需要工具,就在页面上摆着,只看你翻不翻。

我拿到一个Web入口,第一件事就是看页面源码,而且是逐行看。右键查看源码,重点不是看那堆渲染出来的HTML,而是看注释。很多开发者会在代码里留类似<!-- TODO: 修改后台链接 -->、<!-- admin path: /hidden_admin -->这种话。看起来是无心之举,在题目里往往就是出题人故意埋的路标。

JS文件也值得翻。现代站点基本都放了大量JS,这些文件里经常会写着/api/user/info、/api/upload这类接口地址。用浏览器的开发者工具打开页面,切到Sources标签页,把所有JS文件拉出来过一遍。如果你会编程,可以直接写脚本批量抓取页面里链接到的所有JS文件,再用正则搜/api/、token、password这些关键词。CTF里有些后台接口就是这样被发现的,直接访问甚至可能绕过前端校验。

另外,前端调试时经常会有一些隐藏的调试接口或者测试账号,实体展示在页面的某个角落。比如按钮的href指向一个支付跳转地址、某个表单的action指向一个管理后台、某个静态资源路径里出现了疑似内网IP的地址。这些都要记录到笔记里,后面整合利用时很可能用到。

4.3 杂项文件检查:robots.txt、DS_Store与错误页面

最后说几个单独要检查的小文件,这些东西不花多少时间,但经常能有意外收获。

robots.txt算是Web信息收集的必修课。虽然对方写了Disallow不意味着真的不许爬,但它能直接告诉你站点里有哪些目录是管理员不想让搜索引擎看到的。CTF出题人经常会把后台路径、上传目录、隐藏接口写在robots.txt里等你发现。所以目录枚举第一波,我基本会先看一眼/robots.txt。

DS_Store则更冷门一点,它是macOS在文件夹里自动生成的文件,里面记录了该目录下的文件名列表。如果一个公开目录里有DS_Store且可以被访问,你就能用工具把它解析出来,把目录里的所有文件名读出来。以前有专门工具干这事,逻辑也不复杂,本质就是解析二进制格式然后输出文件名。CTF里出现过不少目标站根目录留DS_Store,一解析直接看到一堆源码文件名的情况。

错误页面也有信息量。故意访问一个不存在的路径,看404页面上有没有暴露脚本路径、物理路径、框架版本号。再试着访问一些会触发异常的输入,比如给动态参数传一个数组或者非法字符,如果站点开启了调试模式,报错页可能会直接打印完整堆栈,里面写着代码路径、数据库查询语句、服务器操作系统,这些细节都是下一阶段利用的信息燃料。

5. 常见问题与排查技巧实录

5.1 漏服务比慢服务更致命:扫描完整性

端口扫描这块我踩过一个很大的坑。之前有一道题,拿过来nmap默认参数扫了一圈,只有80端口开着,于是我在80上翻来覆去搞了很久,什么线索都没有。最后别人提醒我,这个题目服务的实际入口在一个高位端口上,我不信邪地把那个IP的65535个端口全扫了一遍,发现果然在40000多端口上开着一个表单页面。

问题的根源就在于默认端口列表太短了。nmap不加-p-的情况下,默认只会扫它内置的热门端口清单,可能只有一千来个。CTF题目为了让选手多走一步,经常会把服务挂在高位端口上。所以现在我的流程里,只要环境允许,一定先跑一次全端口扫描,哪怕速度慢一点,也不给漏服务留机会。

补充一句,如果全端口扫描在比赛环境里实在慢得受不了,可以分两步:先快速扫常见端口,比如-p 1-10000,同时开一个后台全端口扫描任务慢慢跑。这样既能先上手处理已知服务,又不会漏掉高位端口。

5.2 结果要动手验证:误报比空结果更坑

目录扫描的误报问题也值得单独说一下。有些服务器配置了统一错误页面,所有不存在的路径都会返回200状态码,同时输出同一个页面内容。这种情况下,扫描器会疯狂报结果,几十个路径全是“200”,但访问之后发现内容完全一样,全是无用信息。

怎么验证?很简单,随便找一个肯定不存在的路径,比如/this_path_does_not_exist_12345,看它返回的状态码和内容。如果不存在的路径也返回200且内容与“命中”的路径一致,那这批结果全是误报,直接作废。反过来,如果某条命中的路径返回200而错误路径返回404,那这条结果才值得进一步调查。

遇到全站200的情况,就应该调整策略:不要再依赖目录扫描找路径,而是转换思路去看参数、接口、POST行为,或者直接尝试访问框架特有的路径,因为这些路径即便返回相同状态码,也可能有独立的处理逻辑。

另一个常见问题是“访问目录显示403,但文件名存在”。403不一定证明“存在且不能访问”,也可能只是Web服务器对该目录的访问配置了禁止列表,但目录下具体某个文件仍然可以直接读取。碰到这种情况,我会对目录下的文件名做一次批量试探,比如手动构造常见的备份文件名逐个尝试,不少题目的隐藏入口就是这么试出来的。

5.3 字典选不好等于白扫:沉淀自己的工具集

字典真的是信息收集的核心资产。工具是通用的,你的字典决定了你能扫出什么。内置字典在真实渗透里可能够用,但在CTF里往往不够针对。

我现在的做法是维护一个自己的CTF字典,大概几百条,全都是过往比赛里考过的路径关键词:admin、backup、flag、upload、download、api、console、test、tmp、logs、phpmyadmin、editor等等。每次跑完大赛之后,我会把比赛中命中的路径整理下来,沉淀进字典里。这个习惯坚持下来,再遇到新题时命中率会越来越高。

工具集也是同理。不要到比赛现场才去下载各种脚本,提前把常用的信息收集工具都准备到一个干净的目录里,包括端口扫描、目录扫描、git泄露恢复、DS_Store解析、指纹识别这类工具。我的个人习惯是分类放好,用的时候直接按需调用。比赛期间最怕的不是工具不够,而是临时找工具、装依赖,时间就这么白白流走了。

再有一个经验是:信息收集的每一步都要留笔记。别太相信自己的记忆力,扫描结果、可疑路径、已经试过的思路、还没验证的线索,都用文档按时间顺序记下来。一道综合题的信息量足够大,如果没有记录,过半小时你很可能忘了某个端口上还有一个未验证的服务,或者某个目录已经尝试过但还没深入。

我自己打CTF的体会是,信息收集这个环节,比的从来不是谁工具多,而是谁更细、更有条理。被动信息、主动扫描、源码挖掘这三个层面紧密结合,几乎可以解决百分之八十的常规题目。哪怕是一些看起来需要硬核利用的题目,入口往往也是从信息收集阶段的一个不起眼线索串起来的。把这套流程练熟,在比赛里你会明显感觉自己不再是无头苍蝇,而是一个手里有地图的人。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进