文章总结: WordPress插件Forminator存在未认证任意短代码执行漏洞CVE-2026-92229,影响1.57.2及之前版本,1.57.3已修复。漏洞源于AJAX钩子未认证获取nonce,测验模块currenturl参数经escurl绕过后可注入短代码并执行。建议立即升级至1.57.3或更高版本。
综合评分: 85
文章分类: 漏洞分析,WEB安全
WordPress插件Forminator未认证短代码执行漏洞(poc已公开)CVE-2026-92229
YGnight
YGnight
night安全
2026年9月24日 08:00
四川
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
一、漏洞描述
Forminator Forms 是一个WordPress的表单插件,联系表单、支付收款、测验和投票等,插件声明需要 WordPress 6.4 起。近期被爆出存在未授权任意段代码执行漏洞,漏洞产生的入口挂在 WordPress 的 admin-ajax.php 上,注册钩子时同时挂了 nopriv 分支,不检查有没有登录。
受影响区间是 1.57.2 及之前所有版本,1.57.3 修掉,发布时间 9 月 17 日。
站点得开着测验模块才踩到这条分支,只摆一个联系表单的不在命中范围内。
| | |
| — | — |
| CVE 编号 | CVE-2026-92229 |
| 漏洞类型 | 未认证任意短代码执行,CWE-94 |
| 影响组件 | Forminator Forms 插件测验模块的 quizzes/front/front-action.php 结果渲染,以及 abstracts/abstract-class-front-action.php 的 POST 数据入口 |
| 受影响版本 | 1.57.2 及之前全部版本 |
| 修复版本 | 1.57.3,WordPress 插件仓库 changeset 3700724 |
| 请求入口 | /wp-admin/admin-ajax.php,action 为 forminator_submit_form_quizzes 与 forminator_submit_preview_form_quizzes |
| 触发前提 | 站点启用了测验模块,攻击方能从页面解析出测验答案,或手工填入 answers 参数 |
| 危害面 | 以站点已注册短代码的执行结果为上限,取决于同装的插件与主题 |
| CVSS | 9.1,CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
二、漏洞原理
WordPress 的 AJAX 钩子留了两套。
WordPress 给 admin-ajax.php 的请求留了两套钩子,wp_ajax_ 走登录用户,wp_ajax_nopriv_ 对所有人开放,Forminator 两个都挂上了。
表单提交那一段卡着 nonce 校验,看着像把外人挡在外面。
插件自己留了一个取 nonce 的接口,同样挂在 nopriv 上,任何人 POST 一次带 action 与 form_id 的请求就能换到有效值。
// library/abstracts/abstract-class-front-action.php 1.57.2
139 add_action( ‘wp_ajax_forminator_get_nonce’, array( $this, ‘get_nonce’ ) );
140 add_action( ‘wp_ajax_nopriv_forminator_get_nonce’, array( $this, ‘get_nonce’ ) );
1217 public function get_nonce() {
1218 $form_id = filter_input( INPUT_POST, ‘form_id’, FILTER_VALIDATE_INT );
1219 wp_send_json_success( wp_create_nonce( ‘forminator_submit_form’ . $form_id ) );
1220 } // 返回的正是 54 行那次校验要用的值
拿到这个 nonce,再拼一个 action 为 forminator_submit_form_quizzes 的 POST 请求就够了。
测验答案能从页面 HTML 里抠出来。预览接口同走一条路,action 换成 forminator_submit_preview_form_quizzes,还不用落库。
再看 current_url 这条线。
所有 POST 字段进来只过一遍通用的递归清洗,current_url 没有专属处理。
// library/abstracts/abstract-class-front-action.php 1.57.2
973 $post_data = Forminator_Core::sanitize_array( $_POST );
// library/modules/quizzes/front/front-action.php 1.57.2
60 if ( empty( self::$prepared_data[‘current_url’] ) ) {
61 self::$prepared_data[‘current_url’] = forminator_get_current_url();
62 }
岔子出在测验结果的渲染。
社交分享那一段把 current_url 塞进了 data-url 属性,外面套的是 WordPress 自带的 esc_url。
// library/modules/quizzes/front/front-action.php 1.57.2
835