CTF 的 Misc 和 Web 方向里,Whois 这种题目属于典型的“看着简单,动手才知道水有多深”的题型。你可能以为它就是查一下域名注册信息,然后把结果里藏着的 flag 复制出来提交,实际上这道题能延伸出不少信息收集的思路。这篇就按我自己的解题习惯,从题型分析、工具选型、完整实操到踩坑记录,把这道题从头到尾拆一遍,也聊聊它背后真正想考察的东西。不管你是刚入门 CTF 的新手,还是已经刷过一些题的老手,这篇应该都能给你一些可复用的经验。
1. 先认清题型:这道 Whois 题到底考什么
1.1 题目形态与常见变体
先说最常见的形态。题目往往会直接给出一个域名,比如example.com之类,要求你通过 whois 查询拿到隐藏的 flag。这种题看起来没有攻击面,没有参数注入,没有文件上传,唯一能动手的地方就是“查资料”,所以很多人会轻视它,觉得搜一下复制粘贴就完事了。
我见过这个题目的几种变体,先列出来,后面实操部分会逐个拆解法:
- 直接给出域名,让查询后提交 flag 字段;
- 给出一个 IP 地址,要求反查 whois 归属信息;
- 题目页面只贴了一段脱敏后的 whois 输出,要求推理出完整 flag;
- 给出一个看起来不完整的字符串片段,要求先识别出这是域名,再继续查询;
- 把 flag 藏在某个不容易注意的字段,比如 Registrant Organization、DNSSEC 信息、法律声明文本里。
第一眼看上去,这些变体考的东西都不一样,但它们背后有个共同点:都在考察你能否从被动信息中主动定位关键线索。whois 查询本身没有任何攻击行为,它只是向公共数据库要一份公开记录。但恰恰是这种公开记录,在真实渗透测试里经常能暴露注册人联系方式、邮箱、服务器 IP 段、DNS 托管商等敏感线索。CTF 把它单独拿出来当一道题,其实就是把“信息收集阶段最重要的一个动作”放大到了极致。
1.2 信息收集能力为什么是 CTF 的底层能力
很多新手刷题时喜欢直接上手扫描器、爆破工具,总觉得“动静越大越接近答案”。但实际做过几套题就会发现,大量题目真正的难点不是利用漏洞,而是找到那个可被利用的入口。Whois 就是典型的“找入口”题目。
我对信息收集的理解可以概括成三句话:先做被动收集,再做主动探测;先用现成工具,再手写脚本补盲区;先把原始输出完整留存,再考虑用什么姿势去解析。这套思路放在 whois 题目上一样成立。你在做题时如果先养成了这种“慢一步、稳一步”的习惯,后面做子域名枚举、JS 文件分析、历史 DNS 记录查询时,都会顺手很多。
所以这道题表面考一个命令,内里考的是一整套方法论。这也是我建议新手不要跳题的原因。
2. 查询工具选型:别让工具成为你的短板
2.1 在线查询、命令行、脚本三种方式的取舍
关于 whois 查询,我见过有人打开在线网页工具,也有人直接用系统命令行,还有人自己写脚本批量查。三种方式本身不冲突,重点是要明白各自的边界在哪里。
在线网页工具对新手最友好,打开页面输入域名,点查询,结果一目了然。但它的缺点也很明显:很多在线工具为了排版美观,会把原始记录里的一部分字段过滤掉,或者只展示“常见字段”,而 CTF 出题人恰恰喜欢把 flag 放在那些不常见字段里。所以我不建议把它作为解题首选,更适合用来做快速验证。
命令行工具是大多数情况下的首选。它直接向 whois 服务器发起查询,返回的是完整原始文本,不经过前端加工。只要你的系统装上whois命令,一条命令就能拿到全部记录。对于解题来说,信息越多,越不可能漏掉 flag。
脚本则是批量化场景的主力。比如题目给你一个域名列表,或者需要组合多种查询参数,手写一个几十行的 Python 脚本,能大幅节省时间。后面我会给出一个可以改改就能用的模板。
2.2 命令行查询的关键参数与输出差异
Linux 系统下,查一个域名的基础命令是:
whois example.com但这里有个隐藏问题:不同系统预装的 whois 实现不一样,有的来自 BSD 系,有的是 GNU 系,有的发行版默认只带一个简化版。输出格式和默认查询服务器都可能不同。我自己在几台机器上对比过,同一域名,有的默认查注册局的服务器,有的默认查注册商的服务器,拿到的字段确实存在差异。所以做题时如果你觉得结果“缺东西”,可以手动指定 whois 服务器,命令是这样:
whois -h whois.example.net example.com上面-h后面的地址只是一个写法示意,你需要根据域名后缀选择对应的权威服务器。这个操作相当于绕过了系统默认的路由逻辑,直接去目标数据库里翻原始档案。很多在线工具不让你指定服务器,而命令行可以,这就是它最大的优势。
另外,有些 whois 版本支持-H参数,用来隐藏版权声明和法律条款。做题的时候我不建议加这个参数,后面踩坑部分会说明原因。
2.3 用 Python 脚本完成自动化查询
当题目不只是一个域名,而是一批域名时,命令行一条条敲太慢,这时可以写个简单脚本。下面这个模板,我平时做题和测试时都在用,逻辑不复杂,核心是调用系统 whois 命令并捕获输出,再按关键词去匹配 flag 格式:
import subprocess import re def query_whois(domain: str) -> str: """调用系统 whois 命令,返回完整输出文本""" result = subprocess.run( ["whois", domain], capture_output=True, text=True, encoding="utf-8", errors="replace", ) return result.stdout def extract_flag(text: str): """用正则匹配常见的 flag 格式,返回所有命中项""" patterns = [ r"flag\{[^}]+\}", r"ctf\{[^}]+\}", r"Bugku\{[^}]+\}", r"FLAG\{[^}]+\}", ] hits = [] for pattern in patterns: hits.extend(re.findall(pattern, text, flags=re.IGNORECASE)) return hits if __name__ == "__main__": domain = input("输入要查询的域名: ").strip() raw = query_whois(domain) # 建议先把完整输出保存下来,再分析 with open("whois_raw.txt", "w", encoding="utf-8") as f: f.write(raw) flags = extract_flag(raw) print("完整输出已保存到 whois_raw.txt") if flags: print("发现疑似 flag:") for f in set(flags): print(f) else: print("未发现直接命中的 flag,请人工检查字段")这个脚本做了三件事:调用系统 whois、保存原始输出、抽取 flag 特征。你可以根据题目给出的 flag 格式改正则,也可以把域名换成 IP 再跑一次。实测下来,这种脚本在处理多道同类题时效率很高,而且完整保存输出的习惯能帮你回溯当时看到了哪些字段。
3. 实操拆解:从域名到 flag 的完整路径
3.1 第一步:识别题目入口,别把入口当成干扰信息
有些题目不会直接告诉你“这是一个域名”,而是给一段很长的字符串,比如dXBsb2Fkcy5leGFtcGxlLmNvbQ==。你如果只盯着 Base64 解码,解出来是uploads.example.com,这时候很多人才反应过来要查 whois。但也有人解完就停了,以为这就是答案,其实真正的 flag 藏在后续查询里。
所以我的建议是:拿到题目任何文本线索后,先列出“它可能是什么格式”。是不是域名?是不是 IP?是不是编码后的字符串?如果是域名,就立刻查 whois;如果是 IP,就做反查;如果都不是,再从题目描述里找暗示。
这一步没有技术难度,拼的是细心程度。我见过不少人在入口识别上耗了很久,不是因为不会查,而是因为根本没往 whois 的方向想。你可以像我一样,在笔记本上维护一个“格式识别 checklist”:带点号且以常见顶级域结尾的一律先当域名处理;纯数字分段的一律先试 IP 归属;包含=或_的一律先做编码识别。这套清单用熟了,入口识别就能进入“肌肉记忆”的状态。
3.2 第二步:查询 whois 并定位可疑字段
假设你已经确认题目给的是example.com,直接在终端执行:
whois example.com输出会有几十行甚至上百行,不要只看前几行。通常 whois 记录会包含这些字段,我对每个字段的“藏匿价值”做了一个简单归类:
| 字段 | 常规含义 | 隐藏 flag 的可能性 |
|---|---|---|
| Domain Name | 域名主体 | 低,基本是题干复现 |
| Registrar | 注册商名称 | 低 |
| Registrant Organization | 注册机构/个人名称 | 中高 |
| Registrant Email | 注册人邮箱 | 高 |
| Registrant Country/State | 注册所在地 | 中 |
| Creation Date | 创建时间 | 低,但可能隐藏时间戳 |
| Registry Expiry Date | 到期时间 | 低 |
| Name Server | DNS 服务器 | 中高 |
| DNSSEC | 域名安全扩展信息 | 中高 |
| Status | 域名状态码 | 中 |
| 法律声明部分 | 版权公告 | 中,偶尔藏 flag |
重点检查三个位置:邮箱地址、Organization 名称、Name Server 列表。这三个位置格式自由度相对较高,出题人可以塞入看似正常的字符串而不会让 whois 记录本身报错。如果发现某个字段的内容看起来像一段乱码或者无意义英文单词,先别跳过,尝试把它放到文本框里看一次完整形态。
还有一种情况是输出里同时包含多个“目标”,例如一个域名可能关联多个 name server,每个 NS 记录都形似域名,但其实某一个隐藏了 flag 片段。需要逐条检查,避免只看到第一行就收工。
3.3 第三步:提取 flag,三类最常见藏法
我在做过的 Whois 题里,把 flag 的藏法归纳成三类,你可以对照排查。
第一类是“明文直给”。比如 Registrant Email 字段写成flag{th1s_is_s0_easy}@example.com,或者 Organization 字段直接是flag{...}。这种最简单,grep 一下就能找到。命令参考:
whois example.com | grep -iE "flag|ctf"第二类是“编码隐藏”。例如字段值是 Base64、十六进制或者倒序字符串,需要先解码。判断依据是看字符集和长度,如果某段字符串只包含A-Za-z0-9+/=,优先考虑 Base64;如果只包含0-9a-f,可能是 hex;如果整体像英文单词但反向读有意义,考虑反转。
第三类是“变形隐藏”。例如把flag写成f1ag、fl4g、FLaG,或把花括号写成其他符号。这时直接 grep 找不到,需要结合人工检查。我自己的习惯是先把输出里的非字段内容过滤掉,然后一行行看可疑字符串的形态。这一步比较枯燥,但出题人往往就赌你不会逐行看。
如果你在题目页面看到的是“脱敏后的 whois 输出片段”,注意观察哪些字段被打了马赛克。脱敏通常只遮住部分字符,剩下的字符量往往刚好能拼出 flag 的剩余部分。这种变体考的是逆向思维,你要像做填空题一样把空缺补全。
3.4 第四步:提交时的格式陷阱
拿到疑似 flag 后别急着复制提交。先确认格式和题目要求的完全一致,尤其是大小写、花括号、冒号、下划线这些细节。我自己踩过最隐蔽的一个坑是:whois 原文里某字段的值包含不可见字符或者首尾空格,复制到提交框后服务器判定不匹配。
更规范的做法是:先用cat -A检查输出行的结尾符号,或者在 Python 里对提取出的字符串执行.strip(),去掉首尾空白。对于无法直接查看的不可见字符,可以把字符串转成十六进制看一眼:
echo "flag字符串" | xxd正常 flag 的 hex 序列里不应该夹杂多余的0a、0d等换行符。如果发现末尾有多余字节,手动清理后再提交。这个步骤听着繁琐,但能帮你避免“明明找到了但提交失败”的尴尬。
4. 实战踩坑实录:whois 查询最容易翻车的四个地方
4.1 服务器不同,结果完全不同
whois 遵循的是一种分布式查询机制,域名注册局、注册商、公共数据库各自维护一部分数据。你向不同服务器发送查询,回执里的字段甚至会互相矛盾。
我遇到过一次,用系统默认命令查一个.com域名,返回的注册人信息是隐私保护的模板,看起来毫无线索。后来我手动指定了该顶级域的权威 whois 服务器,重新查询后,注册人邮箱、原始创建时间、历史状态码全都出来了。同一域名,两种查询路径,结果差别很大。
所以建议在查询前先明确一条规则:如果默认结果不理想,换一个层级的服务器重试。能指定就指定,命令行不支持的情况下,再考虑通过在线接口兜底。做题时不要把第一次输出当成唯一标准,多试几个服务器,可能有意想不到的收获。
4.2 隐私保护和字段脱敏的影响
现在很多域名默认开启隐私保护服务,真实注册人信息被替换为代理邮箱和代理地址。对于真实渗透测试来说,这类保护是一个障碍;但对于 CTF 题目来说,出题人通常会把 flag 放在不受隐私保护影响的字段里。
因为隐私保护只隐藏注册人联系信息,像 Name Server、Creation Date、Status 这些字段依然会保留原始值。你如果只盯 Registrant Email 发现都是代理信息,就换个思路去看 DNS 和状态码。反过来,如果某个字段清晰得异常,比如一串人工痕迹很重的字符串出现在 Organization 字段里,那大概率就是考题本身,不要因为“太显眼”而怀疑它。
4.3 编码与换行导致的误导
whois 协议本身比较古老,大量服务器返回的文本不保证 UTF-8 编码。中文域名查询时可能出现 Punycode 编码,看起来像xn--开头的一串字符,需要先转换才能看懂。
还有一种情况是输出文本的行结尾不统一,有的是\n,有的是\r\n,在 Windows 记事本里打开时会显示成奇怪的符号。这不是信息有问题,而是查看器兼容问题。建议统一使用 VS Code 或者命令行查看,不要用老式记事本。用脚本处理时,尽量显式声明编码,比如前面模板里就用了encoding="utf-8", errors="replace",目的就是避免解析到一半报错。
4.4 缓存与状态字段的干扰
whois 数据有延迟更新和缓存机制。刚注册的域名可能还没有完整记录,刚续费的域名 Expiry Date 可能没刷新。如果你查到一个域名的状态是PENDING DELETE或REDEMPTION PERIOD,可能代表它正处于特殊生命周期,某些字段会被隐藏。
解题时如果遇到结果“不完整”,先确认是不是缓存问题,换台 DNS 或者换个 whois 服务器再看一次。别急着怀疑自己方向错了,有时候就是数据还没同步。另外,某些域名状态字段会和隐私保护字段同时出现,比如clientTransferProhibited,这本身不代表你找错了,它只是注册商加的保护锁。
5. 从一道题到一类题:完善你的信息收集链
5.1 whois 只是起点:域名关联信息挖掘
做完 whois 查询后,很多题并不会就此结束。更常见的出题套路是:whois 里藏了一个子域名或邮箱,你需要顺着这个线索继续往下查。这时候就要调用其他信息收集手段了。
我对域名关联信息的挖掘顺序是:先做 DNS 解析,再查子域名,然后看证书透明度日志,最后才考虑目录扫描和源码审计。前两步和 whois 一样,属于被动收集,几乎不会触发任何告警;后两步可能已经算是主动行为,实际渗透中需要谨慎,但 CTF 环境中可以根据题目设定来调整。
DNS 解析常用工具是dig和nslookup,查看 A 记录、CNAME 记录、MX 记录、TXT 记录。特别是 TXT 记录,经常被用来存放验证字符串,CTF 出题人也很喜欢把 flag 片段塞进 TXT 记录里。查询命令:
dig txt example.com子域名挖掘则可以结合字典枚举和证书透明日志平台来完成。所谓证书透明日志,是指所有公开信任的 TLS 证书都会被记录在公共日志里,而证书里往往包含大量子域名信息。这种查询不需要暴力猜解,只需要按域名去日志里翻历史证书。思路是理解了,具体平台可以按自己习惯选择。
5.2 数字资产测绘:IP 反查与证书透明度
再往后走一步,如果题目给的是 IP 或者你在 whois 里发现了一个 IP 地址,就可以做 IP 反查。反查通常能看到这个 IP 段的归属机构、运营商、地理位置和 CIDR 范围。这些信息能帮助你定位这个 IP 关联的其他域名,形成一个由“域名 → IP → 域名”的环路。
我举个例子:假设 whois 查询结果显示Name Server: ns1.example.net,对example.net再做 DNS 解析,拿到一个 IP,然后对 IP 做反向解析,可能带出同一台服务器上托管的其他域名或虚拟主机记录。到这里,你手里可选的攻面已经从 1 个变成多个。
这类题目本质上就是“信息收集马拉松”,每一环的结果都可能是下一个环节的入口。做题时 LOG 清楚自己的节奏,不要查到一半被某个无关字段带偏。
5.3 一道模拟题串起全部流程
为了让你更有体感,我虚构一个组合型题目场景,把前面所有思路串起来。假设题目只给了一行字:flag 藏在网络里最容易被忽视的角落。这时候我不会盲目扫描,会先做如下动作:
- 尝试从题目文本里提取可能的关键词,比如“网络”、“角落”,但得不到明确域名;
- 检查题目页面的源码、注释、响应头,看有没有隐藏的链接或提示;
- 如果找到
whois-example.com之类域名,第一时间查询 whois; - whois 输出中某个字段指向一段子域名,比如
secret.whois-example.com; - 对该子域名发起 DNS 查询,看是否有解析记录;
- 解析记录返回一个 IP,继续反查 IP 归属,发现另一个关联域名;
- 在新域名的证书透明度日志中找到一个测试环境站点,访问它的源码注释,发现 flag。
这套流程里没有任何一步是“漏洞利用”,每步都是查询和观察,但最终目标就在这种层层递进中被找到。回过头看,whois 只是第一站,却也是最关键的一站,因为后面所有入口都从它延伸开去。
6. 解题工具箱与我的个人使用习惯
最后分享一些我平时做题时的固定习惯,不一定对所有人生效,但至少能省掉一半弯路。
第一个习惯是“任何线索先保存原文”。不管题目给的是域名、IP 还是编码字符串,先把原文原样存到本地文件里。避免在网页里反复刷新导致原始数据丢失,也方便后续用脚本批量处理。
第二个习惯是“一条命令生成完整报告”。我会在解题之后把查询结果、提取出的候选 flag、提交结果都记录到一个 Markdown 文件里。这样做的好处是:如果验证发现提交失败,可以回溯是哪一步出了问题;如果同类型题目再遇到,可以直接翻看旧报告,掌握出题规律。
第三个习惯是“定期检查工具链”。whois 命令在不同环境下的表现差异很大,我一般会在新机器上先跑一遍whois --version确认版本,再跑一个已知域名测试输出是否正常。工具不正常时不要硬着头皮做题,先花三分钟修环境,往往会更省时间。
第四个也是我特别想说的一点:不要只把眼光放在 whois 的正文文本上。完整输出文件里除了查询信息,还有服务器地址、时间戳、状态码等元数据。某些题目不会把 flag 放在文本正文里,而会放在查询返回的 raw response 的某个扩展字段里,比如 whois 服务器的实验性属性。机器阅读可能忽略它,人工逐行看的时候反而容易发现。
最后说一个隐藏技巧:whois 查询结果里如果出现大段版权声明或法律条款,很多人会直接略过,觉得那是模板垃圾信息。但有几次我在声明文本的中间发现过插入的 flag 字符串,它伪装成“条款编号”或者“示例域名”,不仔细看根本发现不了。所以我的习惯是:whois输出无论多长,都至少完整扫一遍,尤其是开头几行和结尾几行。很多 flag 就藏在那些最容易被跳过的位置上。