- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- CLI
【免费下载链接】wpscan
WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contact@wpscan.com
导读
本文以 WPScan 仓库中spec/fixtures/dynamic_finders/plugin_version/mailgun/change_log/CHANGELOG.md这一 Mailgun WordPress 插件官方变更日志为切入点,结合dynamic_finders.yml配置与BodyPattern源码实现,深入讲解 WPScan 如何利用插件自带的 CHANGELOG 文件完成"零请求特征库"式的版本探测(Aggressive Detection)。读完本文,你将掌握 WPScan 动态查找器的配置语法、正则版本提取原理、测试夹具的验证流程,以及如何为插件编写、调试此类指纹。
关联文档是什么:一份被"复用"为指纹的插件变更日志
先明确一个容易混淆的事实:本文所分析的CHANGELOG.md并不是 WPScan 自己维护的更新日志,而是从 Mailgun WordPress 插件中提取的官方 CHANGELOG 文件副本,存放在测试夹具(fixtures)目录中,作为 WPScan 动态查找器(Dynamic Finders)体系的版本指纹样本。
该文件完整记录了 Mailgun WordPress 邮件插件从 0.1(2012-11-21 首发)到 1.7.1(2019-02-07)的全部版本变更历史,例如:
- 1.7.1:
Reinstall settings page for multisites. - 1.7:
Remove settings page for multisites.、Test plugin with PHP 7.2.、Test plugin up to WordPress 5.0.3. - 1.5.14:
Force SSL-secured SMTP connections to use port 465 (SMTPS) to connect, 587 for plain and TLS - 1.5.12:
Add EU endpoint for Mailgun HTTP API - 1.5:
Now using the Mailgun API v3 endpoint!
之所以在版本号前使用=====的分隔标题、且每行以版本号 (日期)起始,正是因为这些格式约定——稳定的"版本号出现在行首"的排版——使它成为可靠的正则指纹来源。
WPScan 为何需要 CHANGELOG 指纹:动态查找器体系概览
WPScan 的插件版本探测并不依赖唯一的指纹来源,而是维护了一套可扩展的"动态查找器"(Dynamic Finders)框架。其核心元数据文件为 lib/wpscan/db/dynamic_finders/base.rb 中的db/dynamic_finders.yml(运行时数据)与 spec/fixtures/db/dynamic_finders.yml(测试夹具数据)。
从 base.rb 的allowed_classes可以看到,当前框架允许的查找器类型有:
| 查找器类型 | 典型用途 |
|---|---|
Comment | 匹配 HTML 注释中的版本信息 |
Xpath | 通过 XPath 提取 HTML 文档中的版本 |
HeaderPattern | 匹配 HTTP 响应头模式 |
BodyPattern | 匹配响应正文(非 HTML 场景,如纯文本文件) |
JavascriptVar | 匹配 JavaScript 变量赋值 |
QueryParameter | 匹配 URL 查询参数中的版本(如?ver=1.7.1) |
ConfigParser | 解析插件配置文件 |
CHANGELOG.md 属于典型的"非 HTML 纯文本"文件,因此 WPScan 为 mailgun 选用的正是BodyPattern方式。
从夹具到配置:mailgun 的 ChangeLog 指纹解析
在 spec/fixtures/db/dynamic_finders.yml 中,mailgun 插件被配置了多个查找器:
mailgun: ChangeLog: class: BodyPattern path: CHANGELOG.md pattern: !ruby/regexp /^(?<v>\d+\.[\.\d]+)/ version: true Readme: path: readme.txt逐项解读这份配置的含义:
ChangeLog:查找器名称(自由命名,用于在结果中标识来源);class: BodyPattern:指定实际的查找器实现类,对应WPScan::Finders::DynamicFinder::WpItemVersion::BodyPattern(见 wp_item_version.rb);path: CHANGELOG.md:目标文件相对路径,即请求http://<target>/wp-content/plugins/mailgun/CHANGELOG.md;pattern: /^(?<v>\d+\.[\.\d]+)/:正文正则,(?<v>...)命名捕获组提取版本号;version: true:标记该查找器产出版本信息,由 plugin.rb 的versions_finders_configs汇总。
正则的版本提取逻辑
/^(?<v>\d+\.[\.\d]+)/逐段拆解:
^:锚定行首,匹配 CHANGELOG 每行以版本号开头的格式(如1.7.1 (2019-02-07));(?<v>...):命名捕获组v,WPScan 将通过Regexp.last_match[:v]取出该分组内容作为版本号;\d+:匹配一个或多个数字(主版本,如1);\.[\.\d]+:匹配.以及后续的.或数字(子版本序列,如.7.1)。
因此对1.7.1 (2019-02-07)这一行,捕获组v的值为1.7.1;对0.1 (2012-11-21),值为0.1。整个文件第一个匹配到的版本号即被采用——这解释了为什么该夹具头部恰好是最新版本 1.7.1。
源码级原理:BodyPattern 如何完成探测
当 WPScan 对目标站点执行攻击性(aggressive)枚举时,会按配置请求CHANGELOG.md,其核心逻辑位于 body_pattern.rb:
def find(response, _opts = {}) return unless response.code != 404 && response.body =~ self.class::PATTERN create_version( Regexp.last_match[:v], interesting_entries: ["#{response.effective_url}, Match: '#{Regexp.last_match}'"] ) end关键点:
- 404 短路:若目标站点不存在该文件(响应码 404),直接返回 nil,不产生版本;
- 正则匹配:对响应正文执行
self.class::PATTERN(即上文的^(?<v>\d+\.[\.\d]+)/),命中后从Regexp.last_match[:v]提取命名捕获组; - 记录来源:
interesting_entries记录"命中的 URL + 完整匹配文本",供审计与测试断言使用。
该类的默认置信度为CONFIDENCE: 60(见 body_pattern.rb),而create_child_class会按配置动态生成子类,将pattern、path、confidence写入类常量——这一点在测试中有直接验证(见下文)。
测试如何验证这套指纹:expected.yml 与 spec
期望结果声明
WPScan 用 spec/fixtures/dynamic_finders/expected.yml 声明"给定夹具站点,应当探测出什么版本":
mailgun: ChangeLog: number: 1.7.1 found_by: Change Log (Aggressive Detection) interesting_entries: - 'http://wp.lab/wp-content/plugins/mailgun/CHANGELOG.md, Match: ''1.7.1'''这精确对应了 BodyPattern 的实现行为:interesting_entries中拼接了请求 URL 与匹配文本,found_by标记来源为 Change Log 的 Aggressive Detection。
单元测试验证配置语义
body_pattern_spec.rb 验证了查找器动态创建逻辑:
- 默认情况下
PATTERN等于配置中的pattern,CONFIDENCE为 60,PATH为 nil; - 配置显式提供
confidence时,CONFIDENCE取配置值; - 配置提供
path(如changelog.txt)时,PATH为对应值。
这印证了动态查找器的"配置即代码"模式:无需为每个插件编写新 Ruby 类,只需在 YAML 中声明路径与正则。整条链路为:dynamic_finders.yml配置 →Plugin.versions_finders_configs汇总 →create_child_class动态生成子类 →BodyPattern#find在扫描时执行匹配 → 测试用expected.yml断言结果。
对扫描者与插件作者的实践启示
对扫描使用者
- WPScan 通过访问
wp-content/plugins/<slug>/CHANGELOG.md这类公开静态文件即可获得插件版本,属于不依赖漏洞库的指纹探测,即使目标隐藏了 readme.txt 也仍有识别途径; - 探测到的版本信息会进入
interesting_entries与found_by字段,在 CLI/JSON 输出中可直接审计其来源(如Change Log (Aggressive Detection)); - 若插件启用了目录隐藏或对静态文件 404,则该指纹自动失效(
response.code != 404判断),这是 WPScan 设计上的自我保护。
对指纹/插件作者
- 编写新的 ChangeLog 指纹时,确保 CHANGELOG 每行以
版本号开头(=====标题行恰好不匹配^版本号模式,天然被跳过); - 在 spec/fixtures/dynamic_finders/expected.yml 中补充对应的
number、found_by、interesting_entries期望,并在 spec/fixtures/db/dynamic_finders.yml 中声明class: BodyPattern、path、pattern、version: true; - 夹具目录命名遵循
spec/fixtures/dynamic_finders/plugin_version/<slug>/change_log/结构,与 YAML 中的 slug 一一对应。
小结
通过一份 Mailgun 插件的 CHANGELOG.md,我们完整走通了 WPScan 动态查找器的指纹链路:YAML 声明(class: BodyPattern+ 命名捕获组正则)→ 运行时动态生成子类 → 对目标站点静态文件发起请求并正则提取版本 → 测试夹具与expected.yml闭环验证。理解这套机制后,无论是排查 WPScan 扫描结果、还是为 WordPress 插件补充新的版本指纹,你都能快速定位到配置、实现与测试的对应位置。
- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- CLI
【免费下载链接】wpscan
WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contact@wpscan.com
相关推荐
A2UI 评测套件失败分诊实战:从 CI 红灯到本地根因定位
A2UI 评测套件失败分诊实战:从 CI 红灯到本地根因定位 本文基于 eval/TRIAGE.md https://link.gitcode.com/i/dc
网络安全漏洞扫描渗透测试应用安全CLI从一份 changelog 夹具到版本指纹:深入理解 WPScan 对 Members 插件的版本探测机制
从一份 changelog 夹具到版本指纹:深入理解 WPScan 对 Members 插件的版本探测机制 本文以 WPScan 测试夹具 spec/fixtu
网络安全漏洞扫描渗透测试应用安全CLITolaria HTML 块源码编辑统一走 Raw 编辑器:ADR-0155 的设计与实现解析
Tolaria HTML 块源码编辑统一走 Raw 编辑器:ADR 0155 的设计与实现解析 本文基于 Tolaria 仓库中的架构决策记录 docs/adr
网络安全漏洞扫描渗透测试应用安全CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考