
CVE-2026-2002 writeup and Proof-of-concept
Forminator Forms – Contact Form, Payment Form & Custom Form Builder 插件(WordPress)在所有版本中(包括 1.50.2)存在存储型跨站脚本漏洞,该漏洞通过 form_name 参数触发,原因是输入清理和输出转义不足。这使得拥有管理员级别权限的认证攻击者能够在页面中注入任意 Web 脚本,当用户访问被注入的页面时脚本将执行。该插件允许管理员将表单管理权限授予较低级别的用户,因此订阅者等用户也有可能利用此漏洞。
该根因需要对逻辑漏洞的敏锐意识: (位于文件 /fields/html.php 中的函数)
public function markup( $field, $views_obj ) {
$settings = $views_obj->model->settings;
$html = '';
$label = esc_html( self::get_property( 'field_label', $field ) );
$id = self::get_property( 'element_id', $field );
$form_id = false;
$html .= '<div class="forminator-field forminator-merge-tags" data-field="' . $id . '">';
if ( $label ) {
$html .= sprintf(
'<label class="forminator-label">%s</label>',
self::convert_markdown( $label )
);
}
// Check if form_id exist.
if ( isset( $settings['form_id'] ) ) {
$form_id = $settings['form_id'];
}
// To allow iframes in content.
add_filter( 'wp_kses_allowed_html', array( 'Forminator_Core', 'add_iframe_to_kses_allowed_html' ) );
$content = wp_kses_post( self::get_property( 'variations', $field ) ); // root cause here
remove_filter( 'wp_kses_allowed_html', array( 'Forminator_Core', 'add_iframe_to_kses_allowed_html' ) );
$html .= forminator_replace_variables(
$content,
$form_id
);
$html .= '</div>';
return $html;
}
这里的代码使用了清理函数(wp_kses_post)来防止低权限用户的 XSS,但问题在于它在替换变量之前进行了清理。因此,拥有适当权限的攻击者可以利用有效的 HTML 标签绕过 wp_kses_post,并通过变量注入 JavaScript payload 来触发 XSS。
具有编辑表单权限的攻击者可以在 HTML 字段中插入如下 HTML:
然后将 form_name 更改为:
javascript:alert(1) 或 javascript:<Payload>
| 分数 | 严重性 | 版本 | 向量字符串 |
|---|---|---|---|
| 4.4 | 中等 | 3.1 | CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:N |
在我看来,这个漏洞尽管严重性不高,但需要对逻辑和代码审查具备敏锐意识,正如所见,仅仅两行代码之间的一个小错误就造成了漏洞。

如果你喜欢这类研究并希望支持更多深入挖掘,你可以捐赠并支持我。非常感谢你的贡献。
╰(°▽°)╯