1. 项目概述:为什么我们需要WhatWeb这样的工具?
在网络安全评估、渗透测试甚至是日常的资产梳理工作中,我们常常面对一个最基础的问题:“对面这个网站,到底用了什么技术栈?”这个问题看似简单,却至关重要。它决定了后续所有工作的方向——是寻找特定CMS的已知漏洞,还是针对某个JavaScript库的利用方式,亦或是判断其背后服务器的配置弱点。过去,我们可能依赖浏览器的开发者工具手动查看响应头、HTML源码,或者用各种零散的工具去探测,效率低下且容易遗漏。
WhatWeb的出现,正是为了解决这个痛点。它不是一个简单的端口扫描器,而是一个下一代Web指纹识别工具。它的核心能力在于,通过一个简单的命令,就能对目标进行深度探测,识别出超过1800种插件所覆盖的庞杂技术栈,从常见的WordPress、Apache,到不那么起眼的特定版本JavaScript库,甚至是物联网设备的Web管理界面。我把它比作一个经验丰富的“古董鉴定师”,扫一眼(发送一个请求),就能从网站的“蛛丝马迹”中,判断出它的“出身”和“成分”。
对于安全从业者、运维人员乃至开发人员,掌握WhatWeb意味着你拥有了一双透视眼。它能帮你快速绘制攻击面,在红队评估中高效定位脆弱点;在蓝队防守中,快速盘点自身资产暴露的技术信息;在开发运维中,检查第三方组件是否存在已知风险。接下来,我将从安装配置、核心原理、实战技巧到深度定制,带你彻底玩转这款开源利器。
2. WhatWeb核心原理与架构拆解
要精通一个工具,首先要理解它如何工作。WhatWeb的识别逻辑并非魔法,而是基于一套可扩展的、模式匹配的引擎。
2.1 指纹识别的基本逻辑
WhatWeb的识别主要依赖于以下几个信息来源的“特征”匹配:
- HTTP响应头(Headers):这是最直接的信息源。例如,
Server: nginx/1.18.0直接暴露了Web服务器类型和版本;X-Powered-By: PHP/7.4.33指明了后端语言。WhatWeb会解析这些字段进行匹配。 - HTML页面内容(Body):大量技术栈会在生成的HTML中留下独特印记。例如,WordPress页面通常包含
/wp-content/路径的链接或wp-json的标记;特定的JavaScript库如jQuery,其文件路径或版本注释也是特征。WhatWeb使用正则表达式(Regex)在这些内容中进行搜索。 - URL路径与文件(URLs):尝试访问一些默认或特征文件。例如,访问
/robots.txt、/wp-admin/、/phpinfo.php等,通过返回的状态码(200、403、404)和内容来判断。 - Cookie信息:某些应用会在Cookie中设置标识,例如某些CMS的会话Cookie名称。
- 特定请求的响应:通过发送一些特殊的HTTP请求(如修改
User-Agent,请求特定资源),观察目标的反应模式。
WhatWeb将每一种要识别的技术(称为一个“插件”)都定义为一组这样的匹配规则。当对目标发起扫描时,它会并发执行所有相关插件的匹配规则,并汇总结果。
2.2 插件系统与匹配模式
这是WhatWeb最强大的地方。其插件(位于plugins/目录)是用Ruby编写的,结构清晰。一个简单的插件示例如下:
Plugin.define "Example-CMS" do author "Your Name" version "0.1" description "A description of Example-CMS" # 匹配规则 matches [ # 在HTML中搜索文本 { :text => "Powered by Example-CMS" }, # 使用正则表达式匹配版本号 { :version => /Example-CMS v([\d\.]+)/, :regexp_offset => 0 }, # 检查特定的MD5哈希(针对静态文件) { :md5 => "a1b2c3d4e5f678901234567890123456" }, # 检查URL路径 { :url => "/admin/login.php", :status => 200 }, # 匹配HTTP头 { :search => "headers[server]", :regexp => /Example-Server/ } ] end:text: 简单字符串匹配,速度快。:regexp: 正则表达式匹配,功能强大,用于提取复杂模式如版本号。:md5: 对特定URL(如/favicon.ico)返回的内容计算MD5哈希,与已知哈希比对。这种方法非常精确,因为默认图标文件很少改变。:url+:status: 探测特定路径,根据HTTP状态码判断。:search: 在HTTP头的特定字段中进行搜索。
WhatWeb在执行时,会为每个插件计算一个“确信度”(Certainty)。例如,仅匹配到一个通用字符串(如“Powered by”)确信度较低;如果同时匹配到了特征字符串、特定URL和正确的版本号正则,那么确信度就会很高,结果更可靠。
注意: 指纹识别不是100%准确的科学。存在误报(将A识别为B)和漏报(未识别出存在的技术)的可能。高确信度的结果更可信,但任何自动化工具的结果都应作为参考,需要结合人工验证。
2.3 主动式与被动式识别
- 被动式识别(Passive): 仅分析正常HTTP请求的响应。它快速、隐蔽,不会对目标造成额外负载或触发安全警报。WhatWeb的默认扫描模式就是被动的。
- 主动式识别(Aggressive): 除了被动分析,还会主动发起更多探测请求,例如尝试访问管理后台、测试文件、触发错误等。这能发现更多隐藏信息,但噪音大,容易被WAF(Web应用防火墙)或IDS(入侵检测系统)记录。WhatWeb通过
-a或--aggression等级来控制。
理解这些原理,你就能明白为什么WhatWeb的命令行参数那样设计,以及在什么场景下该用什么参数,而不是死记硬背命令。
3. 从零开始:安装、配置与基础扫描
3.1 系统环境与安装指南
WhatWeb基于Ruby开发,因此首要条件是安装Ruby环境。
在Kali Linux / Parrot OS等渗透测试发行版上:这些系统通常预装了WhatWeb。可以直接使用。如果没有,使用包管理器安装:
sudo apt update && sudo apt install whatweb在Ubuntu/Debian系统上:
sudo apt update sudo apt install ruby ruby-dev # 安装Ruby及开发包 sudo gem install whatweb # 使用RubyGems安装在macOS上:推荐使用Homebrew安装,最为方便。
brew install whatweb在Windows上:
- 安装RubyInstaller(从 https://rubyinstaller.org/ 下载)。
- 在安装过程中,务必勾选“Add Ruby executables to your PATH”。
- 安装完成后,打开命令提示符(CMD)或PowerShell,运行:
gem install whatweb
通过Git源码安装(获取最新版):
git clone https://github.com/urbanadventurer/WhatWeb.git cd WhatWeb # 可以直接运行 ./whatweb,或通过bundle安装依赖后使用 # 建议创建一个软链接到系统路径 sudo ln -sf $(pwd)/whatweb /usr/local/bin/whatweb安装完成后,在终端输入whatweb --version验证是否成功。
3.2 你的第一次扫描:参数详解
让我们从一个最简单的命令开始,逐步增加复杂度。
基础扫描:
whatweb example.com这个命令会向example.com发起一个HTTP请求,并使用默认的插件集进行被动识别。输出是彩色的,易于阅读,会显示目标IP、状态码、重定向信息以及识别出的技术。
常用核心参数解析:
-v/--verbose: 详细输出模式。这是我最常使用的参数之一。它会显示扫描的详细过程,包括哪些插件被加载、发送了什么请求、匹配到了什么规则。这对于学习原理和调试异常情况至关重要。whatweb -v example.com-a/--aggression: 设置攻击等级(1-4)。默认是1(被动)。等级提高,会启用更多主动探测插件,增加识别率,但也增加被发现的风险。- 等级1(默认): 被动,仅一次HTTP请求。
- 等级2: 增加对
robots.txt、humans.txt、常见路径的轻量级爬取。 - 等级3: 更深入的目录爬取和文件探测。
- 等级4: 最激进,包含大量可能触发警报的探测。
whatweb -a 3 example.com--color=: 控制颜色输出。never,always,auto(默认)。在将输出重定向到文件或使用管道时,建议用--color=never。whatweb --color=never example.com > result.txt-i/--input-file=: 从文件读取目标列表,每行一个目标(域名或IP)。这是批量扫描的必备参数。whatweb -i targets.txt-o/--output=: 指定输出文件。配合输出格式参数使用。--log-json=,--log-xml=,--log-sql=: 将结果以JSON、XML或SQL格式保存到文件。JSON格式尤其适合后续用jq等工具进行自动化处理。whatweb example.com --log-json=result.json # 使用jq提取所有识别出的CMS名称 cat result.json | jq -r '.[] | .plugins | to_entries[] | select(.key | test("CMS";"i")) | .key'
3.3 输出格式与结果解读
WhatWeb的默认输出是给人看的,而日志输出是给机器处理的。
默认输出示例:
http://example.com [200 OK] Country[UNITED STATES][US], HTTPServer[nginx/1.18.0], IP[192.0.2.1], Title[Example Domain], X-Powered-By[PHP/7.4.33][200 OK]: HTTP状态码。Country: 根据IP地址推断的国家。HTTPServer: 识别出的Web服务器及版本。IP: 解析出的IP地址。Title: 网页标题。X-Powered-By: 识别出的后端技术。
JSON输出深度解析:当你使用--log-json时,会得到一个结构化的数据。一个典型的条目如下:
{ "target": "http://example.com", "http_status": 200, "request_config": { ... }, "plugins": { "Nginx": { "version": "1.18.0", "os": null, "string": "nginx/1.18.0", "module": "headers[server]" }, "PHP": { "version": "7.4.33", "string": "PHP/7.4.33", "module": "headers[x-powered-by]" }, "HTML5": { "certainty": 100 } } }plugins对象包含了所有识别出的技术及其详细信息,如版本、匹配的模块(是从header还是body匹配的)。certainty字段表示确信度(0-100)。这个结构化的数据是进行自动化资产清点、漏洞关联(如将PHP版本与CVE数据库关联)的完美输入。
4. 实战进阶:高效扫描策略与技巧
掌握了基础命令,我们进入实战环节。真实场景中,我们面对的是成百上千的目标,需要的是效率、隐蔽性和结果的可用性。
4.1 批量扫描与性能调优
扫描大量目标时,性能和资源管理是关键。
1. 使用输入文件并控制并发:-t/--max-threads参数用于设置并发线程数。根据你的网络带宽和目标服务器承受能力调整。通常设置在50-100之间比较平衡。
whatweb -i targets.txt -t 50 --color=never --log-json=results.json2. 超时控制:--timeout和--max-retries参数可以防止因个别目标响应慢而卡住整个扫描队列。
whatweb -i targets.txt --timeout=30 --max-retries=13. 速率限制(隐蔽性考量):WhatWeb本身没有内置的速率限制功能。在需要高度隐蔽的测试中,可以结合其他工具。一种方法是使用pv(管道查看器)来限制从目标文件读取的速度,间接控制发起请求的速率。
cat targets.txt | pv -L 10 | xargs -P 5 -I {} whatweb {} --color=never # 解释:pv -L 10 限制每秒读取10行,xargs -P 5 使用5个并行进程,每个进程执行一个whatweb命令。更专业的做法是使用代理池或通过设置--proxy参数将所有流量导向一个可控的代理服务器,在代理层做限速。
4. 结果去重与聚合:如果targets.txt中包含多个指向同一IP或同一应用的域名,结果会有重复。可以在扫描后使用脚本处理JSON结果。例如,用jq按IP和关键插件进行去重:
cat results.json | jq -s 'group_by(.plugins | to_entries | map(select(.key | test("HTTPServer|PHP|WordPress")) | .key + .value.version) | sort | join(",")) | map(.[0])' > unique_results.json4.2 隐蔽扫描与绕过技巧
在授权测试中,我们也希望尽可能减少对目标业务的影响和避免触发安全设备的告警。
1. 降低攻击等级与自定义插件:除非必要,否则使用默认等级1。你可以通过-p/--plugins参数只加载你关心的、噪音低的插件,而不是全部1800多个。
# 只加载与CMS和服务器相关的插件 whatweb -p cms,webserver example.com # 查看所有插件分类 whatweb --list-plugins | grep -i “category”2. 设置自定义User-Agent:一些WAF会拦截默认的WhatWeb User-Agent。你可以使用-U参数将其伪装成普通浏览器。
whatweb -U "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" example.com3. 使用代理和Tor网络:--proxy参数可以指定HTTP代理。结合Tor可以实现匿名扫描(注意法律和授权)。
whatweb --proxy http://127.0.0.1:8080 example.com # 使用Tor代理(需先安装并运行Tor服务) whatweb --proxy socks5://127.0.0.1:9050 example.com4. 随机化延迟(需借助外部脚本):WhatWeb没有内置随机延迟。你可以写一个简单的Bash脚本,在扫描每个目标前随机sleep一段时间。
#!/bin/bash while read target; do whatweb "$target" --color=never sleep $((RANDOM % 10 + 5)) # 随机等待5-15秒 done < targets.txt4.3 与其他工具联动:构建自动化工作流
WhatWeb很少单独使用,它通常是自动化侦察流水线的一环。
1. 与子域名枚举工具联动:使用subfinder、amass、assetfinder等工具发现子域,然后交给WhatWeb进行指纹识别。
subfinder -d example.com -silent | whatweb -i /dev/stdin --log-json=subdomains_tech.json2. 与端口扫描器联动:使用masscan或nmap快速发现开放80/443端口的IP,然后进行Web指纹识别。
nmap -p 80,443,8080,8443 -oG - 192.168.1.0/24 | awk '/open/{print $2}' | whatweb -i /dev/stdin3. 与漏洞扫描器/框架联动:将WhatWeb的JSON结果作为输入,传递给像nuclei这样的漏洞扫描器。Nuclei可以根据识别出的技术(如WordPress:5.9,Nginx:1.18.0)自动加载对应的漏洞检测模板,实现精准打击。
# 假设我们已经有了results.json # 使用jq提取所有存在WordPress的目标URL cat results.json | jq -r '.[] | select(.plugins | has("WordPress")) | .target' > wp_targets.txt # 使用nuclei针对这些WordPress目标进行扫描 nuclei -l wp_targets.txt -t /path/to/wordpress-templates/4. 集成到侦察报告:使用Python脚本解析WhatWeb的JSON输出,生成结构化的HTML或Markdown报告,将技术栈、版本、IP、地理位置等信息可视化呈现。
5. 深度定制:编写你自己的识别插件
当你遇到WhatWeb无法识别的内部系统、新型框架或定制化应用时,编写自定义插件就成了终极解决方案。这让你将个人经验沉淀为可复用的自动化能力。
5.1 插件结构解剖
我们回头仔细看2.2节中的插件示例。一个完整的插件包含以下部分:
Plugin.define “Plugin-Name”: 插件名称,显示在结果中。author,version,description: 元信息。matches: 核心数组,包含一个或多个匹配规则哈希。passive/aggressive块(可选): 可以定义不同攻击等级下的匹配行为。
5.2 动手编写第一个插件:识别一个内部管理系统
假设公司内部使用了一个叫“DragonAdmin”的管理系统,它的登录页面 (/admin/login) 有以下特征:
- 页面标题包含“Dragon Admin Console”。
- 页面底部有版权文字 “© 2023 DragonTech Inc. All Rights Reserved.”。
- 它的
favicon.ico文件的MD5哈希是5a8dd3ad0756c8e6a4b8c2d5f7a1b3c9(假设值)。
我们可以创建一个插件文件,例如dragonadmin.rb,放在WhatWeb的插件目录(通常位于~/.whatweb/plugins/或安装路径的plugins/目录下)。
Plugin.define "DragonAdmin" do author "Your Name" version "0.1" description "DragonTech Internal Administration System" website "http://internal.dragontech.com/" # 被动匹配规则 (等级1) matches [ # 匹配标题 { :text => "<title>Dragon Admin Console</title>" }, # 匹配版权文字,并提取年份 { :regexp => /©\s*(\d{4})\s*DragonTech Inc\. All Rights Reserved\./ }, # 匹配favicon的MD5哈希(高确信度) { :md5 => "5a8dd3ad0756c8e6a4b8c2d5f7a1b3c9", :url => "/favicon.ico" } ] # 激进模式下的额外匹配 (等级2+) aggressive do # 尝试访问一个只有该系统才有的特定API端点 m = [] target_url = Target.new(@base_uri.to_s + "/admin/api/version").to_s status, _, body = http_head(target_url) # 发送HEAD请求 if status == 200 # 如果返回200,再发送GET请求获取内容 _, _, body = http_get(target_url) if body =~ /"product":"DragonAdmin","version":"([\d\.]+)"/ m << { :version => $1, :string => "API Version: #{$1}" } end end m end end关键点解释:
:text匹配简单直接。:regexp使用正则表达式,(\d{4})捕获组用于提取年份,但在这个例子中我们没有使用捕获到的值,如果需要可以像后面那样赋值给:version。:md5匹配非常精确,通常确信度最高。需要先计算好目标文件的标准MD5值。aggressive do块内的代码只会在攻击等级大于1时执行。这里我们演示了如何发送自定义的HTTP请求(http_head,http_get是WhatWeb提供的辅助方法)并解析响应。@base_uri是WhatWeb传入的目标URI对象。
5.3 插件调试与测试
编写完插件后,需要测试。
- 将插件放入正确目录:可以放在全局插件目录,也可以使用
--custom-plugin=/path/to/your/plugin.rb参数临时加载。 - 使用详细模式测试:
在详细输出中,你会看到你的插件被加载,并显示匹配过程。如果whatweb -v --custom-plugin=./dragonadmin.rb http://target-with-dragonadmin.commatches数组中的规则被命中,你会看到类似[DragonAdmin] Matches.的输出。 - 测试激进模式:
观察whatweb -a 2 --custom-plugin=./dragonadmin.rb http://target-with-dragonadmin.comaggressive块中的代码是否执行。
实操心得:编写插件时,优先使用高确信度的特征,如MD5哈希、独特的静态文件路径。字符串和正则匹配要尽可能精确,避免过于通用导致误报。多使用
-v模式观察其他成功插件的匹配过程,这是最好的学习方式。
6. 常见问题排查与性能优化实录
即使工具强大如WhatWeb,在实际操作中也会遇到各种“坑”。这里记录了我踩过的一些典型问题和解决思路。
6.1 扫描速度异常缓慢
- 症状:扫描单个目标或少量目标就耗时极长,甚至卡住。
- 排查与解决:
- 检查网络与DNS:首先
ping或curl一下目标,确认网络连通性和DNS解析正常。缓慢的DNS解析会拖累整个进程。可以尝试使用--no-errors参数忽略一些错误,但根本解决需检查DNS配置。 - 检查目标响应:目标服务器可能响应慢或设置了严格的速率限制。使用
--timeout参数(如--timeout=15)为每个请求设置超时,避免无限等待。 - 线程数过高:过高的
-t线程数可能导致本地端口耗尽或被目标封禁。尝试降低线程数(如-t 10)。 - 插件负载:默认加载所有插件。使用
-p参数只加载特定类别插件(如-p cms,webserver)可以大幅提升速度。 - 系统资源:在资源有限的VPS上运行大量扫描时,监控CPU和内存使用情况。可以考虑使用
nice命令降低进程优先级。
- 检查网络与DNS:首先
6.2 识别结果不准确或漏报
- 症状:明明目标使用了某技术,但WhatWeb没有识别出来;或者识别错了。
- 排查与解决:
- 使用
-v模式:这是最重要的调试手段。查看详细输出,看对应技术的插件是否被加载,发送了哪些请求,匹配规则是否命中。可能特征已经变化,而插件规则未更新。 - 提高攻击等级:有些技术特征隐藏在深层路径或需要特定请求才能触发。尝试
-a 3或-a 4进行更深入的探测。 - 检查目标是否使用了CDN/WAF:CDN可能会修改HTTP头(如隐藏
Server头),WAF可能拦截了WhatWeb的探测请求。尝试直接扫描源站IP(如果已知),或使用-U更换User-Agent。 - 特征过于独特或自定义:对于高度定制或内部系统,通用插件无法识别。这就是需要你编写自定义插件的场景。
- 误报处理:如果识别错误,检查是哪个插件规则导致的。可以临时禁用该插件进行扫描对比:
whatweb --plugins=-PluginName target。
- 使用
6.3 输出结果混乱或格式错误
- 症状:输出到文件的内容包含乱码、颜色代码,或者JSON格式不正确无法解析。
- 排查与解决:
- 颜色代码问题:输出到文件或管道时,务必使用
--color=never禁用终端颜色代码,否则文件里会包含不可见的ANSI转义序列。 - JSON格式错误:当扫描多个目标输出到一个JSON文件时,WhatWeb默认生成的是一个JSON对象数组。但如果扫描过程中被强制中断,JSON文件可能不完整(缺少闭合的
])。建议每个目标输出单独的文件,或者确保扫描完整结束。# 更好的方式:每个目标一个JSON文件(结合循环) while read url; do whatweb "$url" --log-json="results/$(echo $url | sed 's/[^a-zA-Z0-9]/_/g').json" done < targets.txt - 编码问题:如果目标网站使用非UTF-8编码(如GBK),可能导致输出乱码。WhatWeb内部处理编码可能不完美。对于中文环境,这个问题相对少见,但需留意。
- 颜色代码问题:输出到文件或管道时,务必使用
6.4 在自动化管道中集成失败
- 症状:在Shell脚本或Python调用WhatWeb时,进程挂起、输出无法捕获或错误处理困难。
- 排查与解决:
- 超时控制:务必在调用时设置超时。在Bash中可以使用
timeout命令。timeout 30 whatweb example.com --log-json=output.json - 错误流重定向:WhatWeb的错误信息(如无法解析域名)默认输出到标准错误(stderr)。需要将其重定向以便捕获。
whatweb invalid-domain.com 2>> error.log - Python subprocess调用:使用
subprocess模块时,注意处理标准输出、标准错误和返回码。推荐使用subprocess.run并设置timeout、capture_output=True。import subprocess try: result = subprocess.run(['whatweb', 'example.com', '--log-json=-', '--color=never'], capture_output=True, text=True, timeout=60) if result.returncode == 0: json_data = result.stdout # 处理json_data else: print(f"Error: {result.stderr}") except subprocess.TimeoutExpired: print("Scan timed out.")
- 超时控制:务必在调用时设置超时。在Bash中可以使用
6.5 性能优化速查表
| 场景 | 优化策略 | 命令示例 |
|---|---|---|
| 超大规模目标扫描 | 限制并发,分批处理,使用文件输出 | whatweb -i huge_list.txt -t 50 --no-errors --log-json=scan.json |
| 对敏感目标隐蔽扫描 | 降低频率,伪装UA,使用代理 | whatweb -a 1 -U "Mozilla" --proxy=http://proxy:8080 target |
| 只关注特定技术 | 按插件类别筛选,禁用无关插件 | whatweb -p cms,framework target或whatweb --plugins=-Apache target |
| 获取机器可读结果 | 始终使用JSON/XML输出,禁用颜色 | whatweb --log-json=out.json --color=never target |
| 从扫描中排除某些目标 | 预处理目标列表,或用xargs配合grep -v | `cat targets.txt |
| 整合到CI/CD流水线 | 使用Docker镜像,限定超时和资源 | docker run --rm -v $(pwd):/output whatweb --help(需构建镜像) |
掌握这些排查技巧和优化策略,你就能在各种复杂环境下稳定、高效地运用WhatWeb,让它真正成为你手中得心应手的侦察利器。工具是固定的,但人的思路是灵活的,结合具体场景调整策略,才是从“会用”到“精通”的关键。