☰
WPScan 插件版本识别实战:以 Block Catalog 的 CHANGELOG.md 为例解析 ChangeLog 动态发现机制
2026/9/25 3:28:10 网站建设 项目流程
  • 网络安全
  • 漏洞扫描
  • 渗透测试
  • 应用安全
  • 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

项目地址:https://gitcode.com/gh_mirrors/wp/wpscan
点击查看免费下载

本篇文章以 WPScan 仓库中保存的第三方插件 Block Catalog 的 CHANGELOG.md 为研究对象,讲解 WPScan 如何利用插件自带的变更日志文件自动识别插件版本。通过阅读本文,你将掌握 ChangeLog 动态发现机制(Dynamic Finder)的配置格式、底层BodyPattern匹配原理、测试验证方式,以及如何从一份普通的版本历史文档中提取可用的版本指纹。

关联文档的角色定位:一份被当作"版本指纹"的第三方变更日志

在 WPScan 仓库中,spec/fixtures/dynamic_finders/plugin_version/block-catalog/change_log/CHANGELOG.md并不是一份项目自述文档,而是被收录进动态发现(Dynamic Finders)测试夹具体系的第三方插件文件。它的存在价值在于:WPScan 会主动请求目标 WordPress 站点中插件目录下的CHANGELOG.md文件,通过正则匹配其中形如## [x.y.z]的版本标题,从而在无需登录、无需读取 readme.txt 的情况下推断出该插件当前安装的版本号。

该文件遵循 Keep a Changelog 规范,包含从1.0.1(2022-11-21 初始发布)到1.4.0(2022-12-03)的全部历史版本条目,恰好完整覆盖了 WPScan 版本匹配正则所要求的全部格式特征。

CHANGELOG.md 全文解读:Keep a Changelog 格式的版本条目结构

原文档共 54 行,结构非常典型,可拆分为三个层次:

# Changelog All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/). ## [Unreleased] - TBD - todo ## [1.4.0] - 2022-12-03 ...

顶部标题与规范声明

# Changelog是该文件的一级标题,紧随其后的说明文字声明本项目按 Keep a Changelog 标准维护变更记录。这一声明本身没有版本信息,不会干扰匹配。

[Unreleased]预留区块

## [Unreleased] - TBD是标准的"未发布变更"占位区,当前内容仅为- todo。注意:该标题在 WPScan 的匹配正则下不会被识别为版本(原因见下文"匹配原理"一节),这正是设计上需要规避的误报点。

已发布版本条目

每个正式版本使用## [版本号] - 发布日期的二级标题组织,变更点以无序列表逐条列出。以1.4.0为例:

## [1.4.0] - 2022-12-03 - Improves Core Block Display Titles logic - Fixes parent term for blocks registered without namespace - Improve Reusable Block detection - Add hooks to support nested variations - Adds unit tests

从变更内容可以推断(而非确证),Block Catalog 是一个面向 WordPress 编辑器(Gutenberg)的"块目录/块管理"类插件:它涉及 Core Block 的展示标题逻辑、无命名空间注册块的父级分类(parent term)修正、可复用块(Reusable Block)检测、块变体(variations)嵌套支持,以及后续版本中的批量索引(batch indexing)与 WP CLI 查找命令。

完整版本演进清单

下表完整继承原文档的全部版本条目,并附上各版本的功能要点(均取自 changelog 原文):

版本发布日期主要变更
1.4.02022-12-03改进 Core Block 展示标题逻辑;修复无命名空间注册块的父级 term;改进 Reusable Block 检测;新增嵌套变体支持 hooks;补充单元测试
1.3.22022-11-25更新 readme.txt
1.3.12022-11-25文档小幅更新
1.3.02022-11-25支持分层分类(hierarchical classification);改进 WP CLI find 命令;补充内联 filter hook 文档;更新截图
1.2.22022-11-25更新文档
1.2.12022-11-25改进默认标题缺失时的块标题检测;首次 SVN 发布
1.2.02022-11-24使用 wp_kses 改进过滤输出
1.1.02022-11-23改进大站点的批量索引;将删除索引重构为批量模式;改进 WP-Admin 中索引与删除的错误处理
1.0.12022-11-21初始发布

WPScan 如何消费这份 CHANGELOG.md:动态发现配置解析

WPScan 并不靠"猜"来识别CHANGELOG.md,一切行为都由数据库文件 spec/fixtures/db/dynamic_finders.yml 中的条目驱动。该文件中block-catalog插件对应的配置为:

block-catalog: ChangeLog: class: BodyPattern path: CHANGELOG.md pattern: !ruby/regexp /\#\# \[(?<v>\d+\.[\.\d]+)\]/ version: true Readme: path: readme.txt

逐项拆解这份配置:

  • ChangeLog:动态发现器的名称,代表"通过变更日志文件识别版本"这一发现方式。
  • class: BodyPattern:指定使用的匹配器类型。WPScan 对动态发现器类型有严格白名单,见 lib/wpscan/db/dynamic_finders/base.rb 中allowed_classes定义:Comment、Xpath、HeaderPattern、BodyPattern、JavascriptVar、QueryParameter、ConfigParser。BodyPattern适用于响应体不是 HTML 文档(无法用 Xpath 解析)的场景,CHANGELOG.md正是这类纯文本文件。
  • path: CHANGELOG.md:目标插件目录下的相对路径,WPScan 会拼接为wp-content/plugins/block-catalog/CHANGELOG.md进行请求。
  • pattern: /\#\# \[(?<v>\d+\.[\.\d]+)\]/:核心版本匹配正则,使用了命名捕获组(?<v>...)提取版本号。
  • version: true:标记该条目产出的是版本信息。

正则匹配原理与边界行为

正则/\#\# \[(?<v>\d+\.[\.\d]+)\]/的匹配逻辑:

  • \#\# \[精确匹配字面量## [;
  • (?<v>...)命名捕获组v捕获版本号;
  • \d+\.匹配至少一位数字加一个点号(如1.);
  • [\.\d]+继续匹配点号或数字的任意组合(如4.0、0.1)。

因此它能正确匹配## [1.4.0]、## [1.0.1]等全部已发布版本标题,并将1.4.0作为捕获结果。同时,由于[Unreleased]中Unreleased不是数字开头,## [Unreleased] - TBD会被正则跳过,从而避免将未发布占位区误判为版本——这正是该格式被选作指纹的原因之一。

WPScan 取到的是该文件中第一个命中的版本标题(即最高版本1.4.0),这也是预期测试结果所验证的行为。

底层实现:BodyPattern 动态发现器如何工作

配置中的class: BodyPattern对应源码 lib/wpscan/finders/dynamic_finder/version/body_pattern.rb。其核心find方法逻辑为:

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

要点:

  1. HTTP 状态过滤:响应码为 404 时直接返回(文件不存在即跳过),保证发现过程只针对真实存在的CHANGELOG.md;
  2. 正则匹配:将响应体与配置中的PATTERN比对,self.class::PATTERN正是由 dynamic_finders.yml 的pattern字段在运行时注入的子类常量;
  3. 版本提取:通过Regexp.last_match[:v]取出命名捕获组v的值作为版本号;
  4. 证据留痕:将effective_url与完整匹配文本写入interesting_entries,最终呈现在扫描报告的 "Interesting Entries" 中,便于审计人员复核。

此外,child_class_constants为 BodyPattern 设置了默认置信度CONFIDENCE: 60(见 body_pattern.rb)。由于block-catalog的配置未显式声明confidence,该发现结果即采用默认置信度 60。

BodyPattern 的子类由create_child_class机制按需生成,其常量注入与默认值行为由测试 spec/lib/finders/dynamic_finder/version/body_pattern_spec.rb 覆盖:测试验证了无显式confidence时继承默认值 60、显式传入path与confidence时的覆盖行为,以及PATTERN从配置注入的正确性。

测试验证:预期结果如何锚定这份指纹

WPScan 为每个动态发现条目都准备了期望结果(Expected),block-catalog的 ChangeLog 条目对应 spec/fixtures/dynamic_finders/expected.yml:

block-catalog: ChangeLog: number: 1.4.0 found_by: Change Log (Aggressive Detection) interesting_entries: - 'http://wp.lab/wp-content/plugins/block-catalog/CHANGELOG.md, Match: ''## [1.4.0]'''

该期望文件明确锁定了三个事实:

  • 识别出的版本号为1.4.0——即 CHANGELOG.md 中第一个命中的版本条目;
  • 发现方式标注为Change Log (Aggressive Detection)——说明该发现器属于积极检测(Aggressive)阶段,会在插件目录被确认后主动请求CHANGELOG.md;
  • 命中证据为CHANGELOG.md, Match: '## [1.4.0]'——与 BodyPattern 实现中interesting_entries的记录格式完全一致,形成"配置 → 实现 → 期望"的闭环验证。

与 Readme 中 "ChangeLog Section" 机制的区别

需要注意区分两套相似的机制:本文讨论的 ChangeLog 动态发现器针对独立的CHANGELOG.md文件;而 spec/app/finders/plugin_version/readme_spec.rb 中定义的changelog_section则是Readme 发现器内部的子能力——它从插件自带的readme.txt正文中解析 "Changelog" 段落(置信度 50)。两者路径不同(CHANGELOG.mdvsreadme.txt)、置信度不同(默认 60 vs 50)、found_by标注也不同(Change LogvsReadme - ChangeLog Section),在分析 WPScan 报告时应加以区分。

实战意义:为什么攻击者视角下 CHANGELOG.md 是重要指纹

从安全扫描的角度看,这份 changelog 至少有四层价值:

  1. 版本确认成本低:CHANGELOG.md是插件作者随源码发布的标准文件,路径可预测、内容为纯文本,无需 JS 渲染、无需解析复杂 HTML,BodyPattern 一次请求即可完成匹配;
  2. 版本粒度精确:与依赖readme.txt中 "Stable Tag" 的机制不同,changelog 记录了每一个补丁版本(如1.3.1、1.3.2这类仅更新文档的版本),可用于精确判断站点是否落后于修复漏洞的最新版本;
  3. 审计可复现:interesting_entries中保存的实际匹配文本,让漏洞研究人员能回溯到具体的指纹命中位置;
  4. 与漏洞数据库联动:识别出的1.4.0版本号会进入后续的漏洞匹配流程,与 WPScan 漏洞库中的该插件历史漏洞(影响范围通常标注为"低于某版本")进行比对,从而判断目标站点是否暴露在已知漏洞下。

当你在 WPScan 扫描报告中看到Change Log (Aggressive Detection)与形如Match: '## [1.4.0]'的条目时,意味着扫描器正是通过本文剖析的这条"配置 → BodyPattern → 正则 → 期望校验"链路,仅凭一个公开的CHANGELOG.md文件就完成了对目标站点插件版本的精确指纹识别。

小结

以 Block Catalog 的 CHANGELOG.md 为样本,可以完整还原 WPScan 版本识别体系中的一个关键环节:配置在 spec/fixtures/db/dynamic_finders.yml(class: BodyPattern、path: CHANGELOG.md、命名捕获正则)、实现在 lib/wpscan/finders/dynamic_finder/version/body_pattern.rb、期望锚定在 spec/fixtures/dynamic_finders/expected.yml。理解了这一链路,你既能读懂扫描报告中的Change Log (Aggressive Detection)结论来源,也能在为自有资产做加固评估时,意识到一份看似无害的变更日志文件本身就是可被自动化利用的版本泄露面。

  • 网络安全
  • 漏洞扫描
  • 渗透测试
  • 应用安全
  • 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

项目地址:https://gitcode.com/gh_mirrors/wp/wpscan
点击查看免费下载

相关推荐

上一篇:5个关键策略:Linaria零运行时CSS与Jest单元测试完美集成指南
下一篇:Apache Arrow 贡献者开发指南:Git 协作规范、Pull Request 流程与字节序设计决策

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询