更新 2023-06-12:你不再需要代码片段。WPManageNinja 在公开披露两小时后(报告后 93 天)修补了漏洞。
更新 2024-01-27:相关的永远哈希值问题现已完全解决。
tl;dr 攻击者可以查看和编辑 FluentCRM 中的联系人详情。WPManageNinja 在 90 天负责任披露窗口期内未修补漏洞。我提供了一个缓解代码片段,以防止在等待官方补丁时利用漏洞。
今天,我将发布关于我在 WPManageNinja 开发的流行 WordPress 插件 FluentCRM 中发现的一个漏洞的信息。该漏洞编号为 CVE-2023-1430,由 FluentCRM 使用电子邮件地址哈希作为授权控制不足引起。我根据 Google Zero 的漏洞披露政策负责任地披露了该漏洞。WPManageNinja 既未在 90 天窗口期内提供补丁,也未请求延期。
在本报告中,contact 指 FluentCRM 联系人对象,而 user 指 WordPress 用户对象。联系人可以链接到用户,但并非必需。有关利用漏洞的详细信息将在官方补丁可用之前保留。安全专业人员可以联系我获取完整报告([email protected])。
在运行 FluentCRM 的网站上,攻击者可以通过知道联系人的电子邮件地址来查看和编辑联系人的姓名、电子邮件地址和列表设置。由于联系人的姓名通常通过合并标签包含在新闻通讯中,攻击者可以用粗俗语言替换联系人的姓名,导致网站所有者发送粗俗的新闻通讯。如果网站管理员启用了 FluentCRM 的偏好管理短代码并将其添加到公共网页,攻击者可以查看和编辑所有暴露的个人信息,即头衔、电话号码、出生日期和地址(取决于 FluentCRM 配置)。
FluentCRM 安装在 30,000 多个网站上。FluentCRM 网站管理员可以通过将我的缓解代码片段添加到其子主题的 functions.php 文件中来防止漏洞利用。
该代码片段并未修补漏洞。它会将 FluentCRM 的取消订阅页面(unsubscribe.php)和偏好管理页面(manage_subscription.php)上的易受攻击内容替换为一条错误消息,提示联系人改为通过电子邮件联系。错误消息中的电子邮件地址是网站的管理员电子邮件地址(可以在代码片段中更改)。缓解代码片段还确保未登录的访问者无法渲染 FluentCRM 的易受攻击的偏好管理短代码(fluentcrm_pref)。未登录的访问者将看到一条错误消息,提示他们登录。所有字符串均可通过提供的 POT 文件进行翻译。
我建议网站所有者采用我提供的缓解措施或他们自己的相应缓解措施。网站所有者还应验证其 FluentCRM 联系人数据的完整性,并在可能的情况下检查日志以查找潜在的数据泄露。对于以下网站,检查日志尤为重要:
网站指定的数据控制者应根据受影响司法管辖区的法律和法规处理个人信息的潜在数据泄露。
如果 FluentCRM 配置为将联系人的设置同步到其对应的用户,攻击者可以更改用户的姓名。幸运的是,FluentCRM 不会将电子邮件地址从联系人同步到用户。如果 FluentCRM 这样做,此漏洞将导致完全控制网站。攻击者可以通过更改网站管理员的电子邮件地址然后重置管理员密码来获得特权访问。
但是,其他解决方案可以将所有元数据从联系人同步到用户,例如 WP Fusion 和 FluentCRM 的 API。WP Fusion 可能是最流行的第三方插件,用于在 CRM(例如 FluentCRM)和 WordPress 之间同步联系人的元数据。幸运的是,当前版本的 WP Fusion 未挂接到从易受攻击表单初始化的元数据更改。我已通知 WP Fusion 的开发者,他们表示在 WPManageNinja 修补漏洞之前不会解决此限制。
FluentCRM 的 API 也可用于更新联系人和用户数据。使用 FluentCRM API 更新用户电子邮件地址的网站所有者,当从 FluentCRM 的偏好管理页面或短代码发起更新时,必须禁用此更新(或添加我的缓解代码片段,以确保无法从易受攻击的表单更新任何设置)。
FluentCRM 允许联系人从公共网页取消订阅和管理偏好。每个新闻通讯中都包含指向这些页面的链接。在这些页面上所做的更改通过联系人电子邮件地址的 MD5 哈希进行授权,该哈希作为 URL 参数传递。电子邮件地址的 MD5 哈希并非秘密,任何人都可以计算。攻击者可以利用不正确的哈希使用来取消订阅特定联系人,或批量取消订阅已知电子邮件地址的联系人。
虽然取消订阅页面仅依赖 MD5 哈希进行授权,但偏好管理页面需要一个名为 ce_id 的额外 URL 参数。在这种情况下,ce_id 指的是 fc_subscribers 表中联系人的 ID。此 ID 是一个递增的整数。因此,ce_id 值可以通过测试所有可能的值轻松找到(搜索空间是网站历史上注册的联系人数量)。管理员用户可能拥有较低的值。
从偏好管理页面,攻击者还可以窃取联系人的 secure_hash 值。通过更新联系人的电子邮件地址,联系人的“secure_hash”值会存储在名为 fc_hash_secure 的 cookie 中。有了这个 cookie,攻击者可以显示由 FluentCRM 偏好表单短代码提供的所有联系人信息。
前面提到的“secure_hash”是 FluentCRM(在某些情况下)依赖的值,替代或作为 MD5 电子邮件地址哈希的备用。自 FluentCRM 2.8.0 发布以来,取消订阅页面完全依赖 secure_hash 值进行授权。偏好管理页面同时接受新的 secure_hash 值和旧的 MD5 电子邮件地址哈希进行授权。
虽然 secure_hash 值无法从电子邮件地址推导出来,但 FluentCRM 的使用并未遵循良好的安全实践。secure_hash 值在每次联系人创建时生成一次。它从不更新,也从不过期。这很有问题,因为 secure_hash 值包含在每封新闻通讯中。如果攻击者获得了联系人的收件箱访问权限,攻击者可以无限期更改联系人的设置。如果受影响的联系人链接到具有管理员权限的用户,并且电子邮件地址更改从 FluentCRM 同步到 WordPress,那么发送给该联系人的每封新闻通讯都将包含一个永不过期的令牌,可用于接管网站。
我于 2023-03-15 向 WPManageNinja 报告了此相关问题。两个月后(2023-05-15),WPManageNinja 回复说他们的安全顾问认为静态 secure_hash 值不是问题。WPManageNinja 的安全顾问表示“使用这种一次性生成的令牌来标识联系人是可以的”,并且“类似于 SaaS 服务的 API 令牌,这些令牌不会传递给其他联系人,只发送给实际拥有电子邮件地址的联系人”。
WPManageNinja 持开放态度,并告诉我如果我认为这仍然是一个安全问题,请告知他们。我照做了。我解释了为什么 secure_hash 值不能与 API 令牌相比。(API 令牌可以确保仅通过 TLS 连接发送,并且可以限制对 API 令牌的访问。电子邮件中的明文值并非如此。最重要的是,API 令牌可以撤销,而联系人无法撤销 secure_hash 值。)
当天晚些时候,WPManageNinja 感谢了我,并表示他们考虑将电子邮件记录 ID 与哈希结合起来。如果结合自动撤销旧的(基于时间的过期)或之前的(基于计数器的过期)secure_hash 值来实现,这将解决问题。此功能尚未实现,但我认为使用静态哈希值不属于此 CVE 的一部分。
在 2023 年第一季度,我们开始从之前的新闻通讯工具(Sendy)迁移到 FluentCRM。我在将 FluentCRM 与 Nikka Systems Academy (Project Opal) 集成时发现了该漏洞。由于我们用自定义插件替换了 FluentCRM 的订阅管理系统,FluentCRM 的易受攻击表单从未影响过我们的网站或客户数据。
FluentCRM 是一个优秀的插件,但 WPManageNinja 对漏洞披露的处理方式有很大改进空间。以下列表是我对 WPManageNinja 如何改善情况的建议。
话虽如此,我仍然信任 WPManageNinja。所有软件都存在错误,单一的漏洞报告管理不善并不是停止使用其插件的理由。
更新 2023-06-12:他们仍然试图在其更新日志中隐藏漏洞,这让我真正感到担忧。(他们现在已经添加了 CVE。)