- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- 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 除了通过 readme.txt、查询参数等常规手段判断 WordPress 插件版本外,还内置了一套“动态探测器(Dynamic Finder)”机制,可以从插件自身携带的changelog.md变更日志中直接正则提取版本号。本文以仓库中 webman-amplifier 的 changelog 夹具 为核心样本,完整拆解 WPScan 的 Change Log 主动探测链路:从配置声明(dynamic_finders.yml)、正则设计(## (?<v>\d+\.[\.\d]+))、底层匹配实现(BodyPattern),到自动化测试与真实扫描验证。读完本文,你将掌握 WPScan 如何从一段插件更新历史中精准锁定当前版本,并理解其 passive / aggressive 两种探测模式的分工。
一、关联文档是什么:一份真实的 WordPress 插件变更日志快照
在 WPScan 仓库中,changelog.md 并非项目自己的更新日志,而是作为测试夹具(fixture)存放的第三方 WordPress 插件 WebMan Amplifier 的完整 changelog。WebMan Amplifier 是 WebMan 主题家族的一个功能增强插件,其 changelog 记录了从 1.0 到 1.5.7 的全部演进过程,共 1600 余行,覆盖了该插件的核心能力面。
这段历史记录本身信息量极大,它揭示了该插件的能力地图与兼容性演进:
| 版本区间 | 核心主题 |
|---|---|
| 1.0.x | 初始发布,Shortcode Generator、Visual Composer 4.2/4.3 支持、widgets 体系成型 |
| 1.1.x | 加入 Beaver Builder 支持、WordPress 4.0 兼容、Schema.org 标记生成 |
| 1.2.x | 全面转向 SASS、Isotope/bxSlider 脚本升级、图标字体系统重构 |
| 1.3.x | 可访问性(accessibility)大幅改进、移除 IE8 支持、Icon Font 管理后台优化 |
| 1.4.x | Font Awesome 4.7、WordPress 4.7 兼容、WooSidebars 集成 |
| 1.5.x | WordPress 5.0 / Gutenberg 编辑器兼容、WPML 可翻译的 Beaver Builder 元素 |
从 changelog 的 “Files changed” 段落可以推断出插件的内部架构:includes/custom-posts/(自定义文章类型:logos、modules、projects、staff、testimonials)、includes/metabox/(后台 metabox 字段系统)、includes/shortcodes/(短代码定义与渲染器)、includes/widgets/(六种 widget)、includes/shortcodes/page-builder/beaver-builder/与visual-composer/(页面构建器集成)等。这为 WPScan 的版本识别提供了稳定的、可正则化的文本载体——因为每个新版本发布时,changelog 的## x.y.z标题行一定会被更新。
二、WPScan 如何"读懂"这份 changelog:动态探测器配置
WPScan 之所以能从这段 changelog 中提取版本号,靠的是动态探测器数据库 dynamic_finders.yml。在该文件中,webman-amplifier条目下配置了两个探测器:
webman-amplifier: QueryParameter: files: - assets/font/fontello.css version: true ChangeLog: class: BodyPattern path: changelog.md pattern: !ruby/regexp /\#\# (?<v>\d+\.[\.\d]+)/这两条配置分别对应 WPScan 的两种探测模式:
2.1 QueryParameter:被动探测(Passive Detection)
QueryParameter探测器没有path字段,因此属于被动探测。WPScan 在抓取首页 HTML 时,会扫描资源 URL 中的查询参数,例如:
http://wp.lab/wp-content/plugins/webman-amplifier/assets/font/fontello.css?ver=1.5.1从?ver=参数中直接读出插件版本号。在 expected.yml 中,这条路径的期望结果是版本1.5.1,found_by标记为Query Parameter (Passive Detection),置信度仅10——因为?ver=参数可能被缓存插件改写,可信度有限。
2.2 ChangeLog:主动探测(Aggressive Detection)
ChangeLog探测器带有path: changelog.md,因此属于主动探测:扫描器会主动请求插件目录下的changelog.md文件,再按正则提取版本。其关键设计是:
class: BodyPattern:指明使用动态探测器家族中的 BodyPattern 实现类(而非 Xpath、Comment 等);pattern: /\#\# (?<v>\d+\.[\.\d]+)/:正则匹配## 1.5.7这类版本标题行,其中(?<v>...)是命名捕获组,捕获到的数字串即版本号。
从源码结构看,Base#allowed_classes 定义了允许的动态探测器类白名单:Comment、Xpath、HeaderPattern、BodyPattern、JavascriptVar、QueryParameter、ConfigParser;而 Plugin#finder_configs 正是依据配置中path字段的有无,将探测器划分为 passive(无 path,随首页响应被动分析)与 aggressive(有 path,需要额外发起请求)两类。ChangeLog 显然属于后者。
三、Change Log 主动探测的底层实现:BodyPattern
当 WPScan 决定对webman-amplifier执行主动探测时,它会动态创建对应探测类,并调用其aggressive方法。底层实现位于 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该实现要点如下:
- 响应条件:仅当请求
changelog.md返回的状态码不是 404,且响应体与PATTERN正则匹配时才继续; - 版本提取:通过
Regexp.last_match[:v]取正则命名捕获组v的值——这正是配置文件中(?<v>...)的作用; - 置信度:BodyPattern 家族的默认置信度为60(远高于 QueryParameter 的 10),说明 WPScan 认为 changelog 头部版本标题是相对可靠的证据;
- 证据记录:
interesting_entries会把请求 URL 与命中的正则片段一并记录,供--format json等输出格式展示取证信息。
最终,Finder#create_version 会把捕获的数字包装成Model::Version对象,并填充found_by(Change Log (Aggressive Detection))与confidence(60)等元数据。探测类的动态创建则由 Plugin#create_versions_finders 完成:先按 slug 归类出命名空间模块(webman-amplifier→WebmanAmplifier),再以class: BodyPattern解析到WPScan::Finders::DynamicFinder::WpItemVersion::BodyPattern作为父类,为其注入配置生成子类。
需要特别说明的是正则语义:\#\# (?<v>\d+\.[\.\d]+)匹配的是以##开头的行(changelog 中最高版本号始终位于文件最顶端),\d+\.[\.\d]+允许形如1.5.7、1.0.9.15的多段位版本号。对照本夹具,文件首行就是## 1.5.7,因此探测结果为1.5.7。
四、验证闭环:fixture 如何参与自动化测试
WPScan 为每个动态探测器都建立了"配置 → 夹具 → 期望值"的完整测试闭环,webman-amplifier 是其中的典型样本。
4.1 期望结果声明
在 expected.yml 中:
webman-amplifier: QueryParameter: number: 1.5.1 found_by: Query Parameter (Passive Detection) interesting_entries: - http://wp.lab/wp-content/plugins/webman-amplifier/assets/font/fontello.css?ver=1.5.1 confidence: 10 ChangeLog: number: 1.5.7 found_by: Change Log (Aggressive Detection) interesting_entries: - 'http://wp.lab/wp-content/plugins/webman-amplifier/changelog.md, Match: ''## 1.5.7'''注意这里有个非常有意思的细节:被动探测得到 1.5.1,主动探测得到 1.5.7。这说明在夹具模拟的站点中,首页 CSS 的?ver=参数停留在 1.5.1(可能被缓存或未刷新),而插件目录下的 changelog 已经更新到 1.5.7。这正是 WPScan 同时提供两种探测模式的价值:单一信号可能滞后或失真,交叉验证才能逼近真实版本。
4.2 自动化生成的规格测试
plugin_version_spec.rb 会遍历dynamic_finders.yml中所有带version的配置,为每个 slug 动态生成describe块。对带path的 ChangeLog 配置:
- 在
#aggressive分支(第 147-189 行)中,它会 stub 对plugin.url(config['path'])(即.../webman-amplifier/changelog.md)的请求,响应体正是本夹具文件的内容; - 随后断言
finder.aggressive返回的WPScan::Model::Version的number、found_by、interesting_entries与confidence均与 expected.yml 一致; - 由于此类生成的用例数以万计,除每个"父类/路径/版本键"组合的第一个用例外,其余均被标记为
slow: true(仅在全量测试中执行),以保证 PR 阶段的覆盖报告稳定(见 第 19-24 行的注释)。
同时,plugin_spec.rb 从数据库层验证了finder_configs的筛选逻辑:被动模式只返回无path的配置、主动模式只返回有path的配置,以及versions_finders_configs仅收集含version键的条目——这些都是理解 ChangeLog 为何只出现在 aggressive 路径上的直接依据。
4.3 夹具目录结构约定
从仓库结构看,动态探测器夹具遵循"slug / finder_class / path"的目录约定,例如本夹具位于:
spec/fixtures/dynamic_finders/plugin_version/webman-amplifier/change_log/changelog.md即:插件 slug 为webman-amplifier,探测器名为change_log,路径为changelog.md。WPScan 测试基建正是按此约定将配置文件中的path映射到本地夹具文件,从而在无真实站点的情况下完成全链路模拟。
五、实战:如何在自己的目标站点上触发 Change Log 探测
理解了原理之后,可以按以下方式在真实扫描中复现并验证这一探测链路:
1. 以主动模式扫描插件(aggressive 模式才会请求 changelog.md):
ruby wpscan.rb --url https://example.com --plugins-detection aggressive由于 ChangeLog 探测器带有path配置,它只会在 aggressive 阶段被激活;若使用默认的 passive 模式,WPScan 只会从首页响应中寻找无路径的信号(如 QueryParameter)。
2. 观察输出取证信息:当命中时,CLI 输出会显示类似
[+] webman-amplifier | Found By: Change Log (Aggressive Detection) | - https://example.com/wp-content/plugins/webman-amplifier/changelog.md, Match: '## 1.5.7' | Version: 1.5.7 (100% confidence)配合--format json可拿到结构化结果,其中interesting_entries字段即上文 BodyPattern 实现里写入的 "URL, Match: '正则命中片段'" 证据。
3. 交叉验证:若同一插件还配置了 QueryParameter(如本例),可对比 passive 与 aggressive 两个版本号;若不一致,通常以 changelog 头部版本为准(置信度更高),但需注意个别站点会屏蔽或改写过时日志文件,此时两种信号可能同时失真,应再结合 readme.txt 等其余探测手段综合判断。
4. 验证探测逻辑本身:无需真实站点,直接运行仓库内的针对性用例即可:
rspec -e "WPScan::Finders::PluginVersion::WebmanAmplifier::ChangeLog#aggressive"该用例会以 changelog.md 作为 stub 响应体,断言探测结果与 expected.yml 中的1.5.7一致。
六、经验与边界:changelog 探测的适用前提
从本案例可以总结出 Change Log 主动探测的适用前提与局限性:
- 依赖文件可达性:探测的前提是站点未屏蔽
changelog.md的访问(404 时直接放弃,见 body_pattern.rb)。出于安全加固,部分站点会删除或禁止这类信息文件,此时探测器静默失效; - 依赖版本标题格式:
## x.y.z是绝大多数插件 changelog 的通用格式,但若插件改用其他标题样式(如Version 1.5.7、v1.5.7),则需要为该插件单独配置适配的正则;WPScan 的动态配置机制正是为此设计的——每个 slug 的 pattern 可独立定制,无需改动扫描器代码; - 版本信号滞后:changelog 通常在新版本发布时同步更新,但缓存 CDN 可能导致实际加载资源与日志文件版本不一致(本案例中 passive=1.5.1、aggressive=1.5.7 即是典型),因此多信号交叉比对才是可靠做法;
- 取证与置信度:BodyPattern 家族默认置信度为 60,配合
interesting_entries中记录的 URL 与正则命中片段,可为安全评估报告提供可追溯的证据链。
小结
通过 webman-amplifier 这一完整样本,本文梳理了 WPScan Change Log 主动探测的全链路:配置声明(dynamic_finders.yml 中的ChangeLog条目)→ 正则设计(## (?<v>\d+\.[\.\d]+)命名捕获组)→ 底层实现(BodyPattern#find)→ 测试闭环(plugin_version_spec.rb 与 expected.yml)→ 真实扫描验证。这套机制的价值在于:即使插件在首页没有任何版本线索(无?ver=、无 meta 生成器、无 readme),只要其更新日志仍可访问,WPScan 就能以 60 置信度的高可信信号锁定精确版本,为后续漏洞库比对奠定基础。对于安全研究人员与站点维护者而言,理解该探测路径既能读懂 WPScan 报告中的Change Log (Aggressive Detection)出处,也能据此评估自身站点信息暴露面,并针对性地加固(如删除或重命名 changelog 文件)。
- 网络安全
- 漏洞扫描
- 渗透测试
- 应用安全
- 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 插件版本指纹识别实战:以 nerd-wp CHANGELOG.md 测试样本为例解读 "Change Log" 动态指纹器
WPScan 插件版本指纹识别实战:以 nerd wp CHANGELOG.md 测试样本为例解读 "Change Log" 动态指纹器 本文以 WPScan
网络安全漏洞扫描渗透测试应用安全CLIWPScan 动态指纹识别:以 social-divi 的 CHANGELOG.md 为例解析 Change Log 版本探测原理
WPScan 动态指纹识别:以 social divi 的 CHANGELOG.md 为例解析 Change Log 版本探测原理 本文基于 WPScan 仓库
网络安全漏洞扫描渗透测试应用安全CLIWPScan 插件版本检测原理实战:以 mailchimp-for-wp 的 CHANGELOG.md 为例解析 Change Log 动态指纹识别
WPScan 插件版本检测原理实战:以 mailchimp for wp 的 CHANGELOG.md 为例解析 Change Log 动态指纹识别 本指南以
网络安全漏洞扫描渗透测试应用安全CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考