
SureForms <= 2.2.0 - 未认证存储型跨站脚本
SureForms 插件中存在一个严重的存储型 XSS 漏洞。该漏洞源于 entries.js 中不安全的客户端实现:用户输入会被程序化地解码(逆转服务端净化处理),随后通过 dangerouslySetInnerHTML 渲染,且没有进行适当的客户端净化。这使得未认证的攻击者能够通过标准表单字段注入恶意 JavaScript 载荷,绕过 WordPress 默认的 wp_kses 过滤器。
若要验证目标站点是否正在运行 SureForms,请检查翻译文件头,其中通常包含版本号。
目标 URL:
http://target-site.com/wp-content/plugins/sureforms/languages/sureforms.pot
验证命令:
curl -s "http://target-site.com/wp-content/plugins/sureforms/languages/sureforms.pot" | grep "Project-Id-Version"
该漏洞位于基于 React 的管理界面中,该界面负责查看表单条目(entries.js)。
在压缩后的 entries.js 文件中,有一个辅助函数(在分析版本中标识为 Xv),用于处理 HTML 实体。
代码逻辑(重构):
// Function Xv: Pre-processing field values
var Xv = function(input) {
var value = input.value;
// VULNERABILITY ROOT CAUSE:
// If the string contains HTML entities (e.g., <), create a textarea,
// inject the content, and extract the value.
// This effectively DECODES HTML entities back to raw HTML tags.
// Example: "<img ...>" becomes ""
if (typeof value === "string" && value.match(/&[a-zA-Z0-9#]+;/)) {
var textarea = document.createElement("textarea");
textarea.innerHTML = value;
// Logic to revert sanitization
if (textarea.value.includes("<") || textarea.value.includes(">")) {
value = textarea.value; // Now 'value' contains RAW HTML
}
}
return { ...input, value: value };
}
分析: 此函数绕过了后端安全机制。即使 WordPress 正确地将 <script> 以 <script> 形式存储在数据库中,此函数也会在从 API 获取数据后立即将其转换回 <script>。
解码后,数据被传递给渲染组件(标识为 Jv)。
代码逻辑(重构):
// Function Jv: Rendering the field
var Jv = function(props) {
var field = props.field;
var val = field.value; // This value is now raw HTML (post-decoding)
// THE TRIGGER: Check if the string looks like HTML
if (typeof val === "string" && val.match(/<[^>]+>/g)) {
// THE SINK: Render using dangerouslySetInnerHTML WITHOUT client-side sanitization (e.g., DOMPurify)
return React.createElement("span", {
dangerouslySetInnerHTML: { __html: val }
});
}
// Safe render for non-HTML text
return React.createElement("span", null, val);
}
注入: 未认证的攻击者在前端提交表单。攻击者不使用原始 HTML 标签(这些标签会被 WordPress 后端剥离/净化),而是发送HTML 实体。
存储: WordPress 将输入(例如 <img...)视为安全文本并存储在数据库中。
执行(陷阱):
Xv 函数检测到实体,并将 <img... 解码回 ` Entries。单击步骤 1 中提交的条目以查看详情。
结果: 浏览器将执行 JavaScript 载荷(alert('XSS_SUREFORMS'))。