- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- 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 是面向安全专业人员与站点维护者的 WordPress 安全扫描器,其插件/主题版本识别高度依赖一个称为Dynamic Finders(动态查找器)的机制:从插件目录中各类可公开访问的文件(readme.txt、CHANGELOG.md、CSS/JS 资源等)里挖掘版本指纹。本篇将以仓库测试夹具中的一份真实插件变更日志 CHANGELOG.md(beer-blocks 插件)为切入点,完整还原 WPScan 如何把CHANGELOG.md中的版本号解析为"插件版本指纹":从dynamic_finders.yml的配置字段,到BodyPattern查找器的正则提取逻辑,再到置信度与测试夹具在整个流水线中的角色。读完你不仅能读懂 WPScan 的 ChangeLog 探测原理,还能在自己的插件指纹库中复刻这一模式。
一、一份 CHANGELOG 就是一份版本指纹
先看被分析的这份文件本体,它位于仓库测试夹具目录:
spec/fixtures/dynamic_finders/plugin_version/beer-blocks/change_log/CHANGELOG.md
## [1.0.1] - 2021-09-29 - Fix fa-icon block type ## [1.0.0] - 2021-09-29 - First release这是 WordPress 插件beer-blocks的变更日志(2021-09-29 发布 1.0.0 首发版本,同日补丁 1.0.1 修复 fa-icon 区块类型)。从 WPScan 的视角看,这份文件的价值不在文字,而在结构:Markdown 二级标题## [版本号]是高度规整、易于正则提取的版本标记。只要站点上存在可访问的wp-content/plugins/beer-blocks/CHANGELOG.md,扫描器就能据此反推出插件版本,进而关联漏洞数据库判断该版本是否存在已知漏洞。
需要澄清的是:这份文件本身只是 WPScan 测试体系中的输入样例(fixture),它的"技术实质"由其配套的查找器配置与实现代码共同定义。下面我们沿着配置 → 实现 → 测试的链路逐一展开。
二、Dynamic Finders:WPScan 的版本指纹机制
2.1 为什么需要"动态"查找器
WordPress 插件版本识别的传统做法是抓取readme.txt中的Stable tag字段,但许多插件作者不会同步维护该字段,或插件根本不含 readme.txt。Dynamic Finders 的诞生就是为了解决这种不确定性:WPScan 把大量插件的"可探测文件 + 版本提取正则"预编译进一份数据库文件,扫描时按插件 slug 动态实例化对应查找器,逐个探测这些候选文件。
这份数据库即 spec/fixtures/db/dynamic_finders.yml(生产环境对应lib/db/dynamic_finders.yml,由 lib/wpscan/db/dynamic_finders/base.rb 通过YAML.safe_load_file加载,并允许Regexp类以支持正则字面量)。
2.2 允许的查找器类别
lib/wpscan/db/dynamic_finders/base.rb 定义了受支持的查找器类别白名单:
@allowed_classes ||= %i[Comment Xpath HeaderPattern BodyPattern JavascriptVar QueryParameter ConfigParser]Comment/Xpath:解析 HTML 响应中的注释或 DOM 节点;HeaderPattern/BodyPattern:对响应头/响应体做正则匹配(BodyPattern 专门用于响应体不是 HTML 文档的场景,例如纯文本的 CHANGELOG.md);JavascriptVar/QueryParameter/ConfigParser:分别面向 JS 变量、URL 查询参数与配置文件。
base.rb 还通过method_missing暴露passive_*_finder_configs/aggressive_*_finder_configs两类查询入口,供上层按攻击模式(被动/主动)取用配置——这解释了为何同一个插件可以同时配置被动与主动两种指纹。
三、配置解读:beer-blocks 的 ChangeLog 条目
在 spec/fixtures/db/dynamic_finders.yml 中,beer-blocks 的配置如下:
beer-blocks: ChangeLog: class: BodyPattern path: CHANGELOG.md pattern: !ruby/regexp /\#\# \[(?<v>\d+\.[\.\d]+)\]/ version: true Readme: path: readme.txt逐字段拆解:
| 字段 | 值 | 含义 |
|---|---|---|
ChangeLog | (节点名) | 该指纹的语义标签,class指明实际查找器类型 |
class | BodyPattern | 复用BodyPattern版本查找器(白名单内) |
path | CHANGELOG.md | 在插件目录下要探测的相对文件路径,即wp-content/plugins/beer-blocks/CHANGELOG.md |
pattern | /\#\# \[(?<v>\d+\.[\.\d]+)\]/ | 提取版本的 Ruby 正则,含命名捕获组(?<v>...) |
version | true | 该查找器的目标是提取版本号(而非仅确认插件存在) |
Readme | path: readme.txt | 同一插件还可叠加 readme.txt 通道(见第五节) |
3.1 正则的匹配逻辑
以 fixture 文件首行为例## [1.0.1] - 2021-09-29:
\#\# \[匹配字面量## [(\#转义#);- 命名捕获组
(?<v>\d+\.[\.\d]+):\d+匹配1,\.匹配点号,[\.\d]+再吞入.0.1,最终v = "1.0.1"; - 行尾
]完成闭合。
由于扫描器默认对响应体取第一个正则匹配(见下节实现),fixture 中按时间倒序排列的1.0.1会被优先命中——这也是为什么作者总是把最新版本写在 changelog 最前面。
四、源码级原理:BodyPattern 版本查找器
4.1 核心实现
lib/wpscan/finders/dynamic_finder/version/body_pattern.rb 定义了实际执行逻辑:
class BodyPattern < Finders::DynamicFinder::Version::Finder def self.child_class_constants @child_class_constants ||= super.merge(PATTERN: nil, CONFIDENCE: 60) end 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 end关键行为:
- 前置条件:响应码非 404,且响应体与
PATTERN正则匹配。PATTERN由 YAML 配置中的pattern注入(子类常量合并机制); - 版本提取:通过命名捕获组
Regexp.last_match[:v]取出版本字符串——这正是配置里(?<v>...)命名的原因; - 证据留痕:
interesting_entries记录有效URL + 完整匹配串,便于输出报告与复核; - 默认置信度:
CONFIDENCE: 60(未在配置中显式覆盖时的取值)。
4.2 版本对象的组装
lib/wpscan/finders/dynamic_finder/version/finder.rb 中的create_version将字符串包装为Model::Version:
def create_version(number, finding_opts) Model::Version.new(number, version_finding_opts(finding_opts)) end def version_finding_opts(opts) opts[:found_by] ||= found_by opts[:confidence] ||= self.class::CONFIDENCE opts end即每个探测结果会携带found_by(定位方式)与confidence(置信度)两个元数据,供后续漏洞匹配与报告分级使用。
4.3 类别与插件模型的桥接
BodyPattern被同时桥接进两条动态查找器链路:
- lib/wpscan/finders/dynamic_finder/wp_item_version.rb:插件/主题的版本探测(本案例所属链路);
- lib/wpscan/finders/dynamic_finder/wp_version.rb:WordPress 核心版本探测。
五、双通道互补:readme.txt 与 CHANGELOG.md
beer-blocks 的配置同时声明了ChangeLog与Readme两条探测通道,这种组合非常典型。Readme通道对应 app/finders/plugin_version/readme.rb 中的PluginVersion::Readme查找器,其version_numbers方法按优先级收集两处版本信号:
if (number = from_stable_tag(body)) numbers << [number, 'Stable Tag', 80] end if (number = from_changelog_section(body)) numbers << [number, 'ChangeLog Section', 50] endfrom_stable_tag:匹配stable tag: xxx或version: xxx,置信度80;from_changelog_section:用/^=+\s+(?:v(?:ersion)?\s*)?([0-9.-]+)[^=]*=+$/i扫描 readme.txt 内嵌的 Changelog 区块(等号标题风格),取排序后的最大版本,置信度50。
对比可见:readme.txt 中的 Stable Tag 权威性最高,而独立的CHANGELOG.md文件(BodyPattern,置信度 60)与其互为补充——一处缺失或失实时,另一处仍可兜底完成版本判定。三种来源的置信度排序(Stable Tag 80 > CHANGELOG.md 60 > readme 内嵌 Changelog 50)也反映了 WPScan 对信号可靠性的内部评估。
六、测试夹具的角色:如何验证指纹有效性
回到开篇的 fixture 文件,它在仓库中的位置暴露了用途:
spec/fixtures/dynamic_finders/plugin_version/beer-blocks/change_log/CHANGELOG.md从目录结构看(spec/fixtures/dynamic_finders/plugin_version/下按插件 slug 组织、每个插件目录内按查找器类别存放样例),这份文件是动态查找器测试体系的标准输入样例,与 spec/lib/db/dynamic_finders 下的动态查找器测试用例配套使用。其价值在于:
- 确定性验证:用固定内容(
## [1.0.1]与## [1.0.0]两行)验证pattern正则确实能从真实格式的 CHANGELOG 中提取出版本号,防止正则退化; - 格式覆盖:
- Fix fa-icon block type这类非版本行被刻意保留,用于确认正则不会被正文内容误匹配; - 回归保护:任何对
BodyPattern实现或 YAML 配置的改动,都必须保证该样例仍能正确产出1.0.1。
七、小结:一条完整的版本识别链路
把全文串起来,WPScan 对 beer-blocks 这类插件的版本识别可归纳为一条流水线:
- 配置加载:从 dynamic_finders.yml 读取
beer-blocks.ChangeLog条目(class: BodyPattern、path: CHANGELOG.md、pattern正则); - 请求探测:对站点发起
wp-content/plugins/beer-blocks/CHANGELOG.md请求(由动态查找器上层驱动,区分被动/主动模式); - 正则提取:BodyPattern#find 匹配响应体,通过命名捕获组
(?<v>...)取出1.0.1; - 置信度评估:默认置信度 60,与 readme.txt 的 Stable Tag(80)等信号并列;
- 版本建模:create_version 生成带
found_by/confidence/interesting_entries的Model::Version,进入漏洞比对环节。
这份 fixture 文档虽只有两行变更记录,却精准刻画了 WordPress 生态中一种极其普遍的版本信息载体,也展示了 WPScan 如何以"配置 + 正则 + 通用查找器"的组合,用最小成本把任意插件的 CHANGELOG 转化为可用的安全情报。如果你在扩展自己的插件指纹,完全可以照搬这套模式:定义文件路径、编写带命名捕获组的正则、为不同来源分配置信度,并用真实样例做回归测试——这正是本项目 Dynamic Finders 体系留给开发者的最佳实践模板。
- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- 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 插件版本检测实战:以 bonaire 的 CHANGELOG.md 为例解读 ChangeLog 动态查找器
WPScan 插件版本检测实战:以 bonaire 的 CHANGELOG.md 为例解读 ChangeLog 动态查找器 导读 WordPress 插件常常会
网络安全漏洞扫描渗透测试应用安全CLIWPScan 插件版本检测实战:以 gf-heidelpay 的 changelog 解析 ChangeLog 动态查找器原理
WPScan 插件版本检测实战:以 gf heidelpay 的 changelog 解析 ChangeLog 动态查找器原理 WPScan 作为 WordPr
网络安全漏洞扫描渗透测试应用安全CLIWPScan 插件版本识别实战:从 CHANGELOG.md 到 ChangeLog 动态查找器的完整链路
WPScan 插件版本识别实战:从 CHANGELOG.md 到 ChangeLog 动态查找器的完整链路 本文以 WPScan 仓库中 admin dashb
网络安全漏洞扫描渗透测试应用安全CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考