发布于昨天 21:551天前 背景这篇记录放在漏洞库板块,主要针对一次授权环境中的 WordPress 插件漏洞验证过程。目标站点使用 WordPress + WooCommerce + Elementor Pro,业务侧反馈存在异常管理员账号创建记录。经版本核对,Elementor Pro 插件处于受影响版本范围内,风险点集中在 WooCommerce 模块相关的 Ajax 调用权限校验不足。本文不讨论批量利用,只记录单站授权验证、日志排查、漏洞确认、权限边界判断和修复建议。类似漏洞在 WordPress 插件中比较常见:前端 Ajax 接口挂载在 admin-ajax.php,但后端回调缺少能力检查或 nonce 校验,导致低权限用户甚至未认证用户触发敏感逻辑。适用场景站点使用 WordPress,并安装 Elementor Pro 与 WooCommerce。发现异常用户创建、插件配置被修改、后台选项表异常变更。需要在授权渗透测试中验证漏洞是否真实存在。需要判断漏洞影响范围、日志留痕位置以及修复方式。问题定位排查时先确认插件版本,不建议直接从后台页面判断,因为部分站点会隐藏版本号。可以在服务器侧读取插件头信息:cd /var/www/html/wp-content/plugins/elementor-pro # 查看插件版本 sed -n '1,40p' elementor-pro.php | grep -i "Version" # 或直接从 WordPress CLI 查询 wp plugin list | grep -E "elementor|woocommerce"一次现场环境中的版本信息如下:elementor-pro active none 3.11.x woocommerce active none 7.x wordpress 6.x同时检查是否存在异常用户和可疑时间线:wp user list --fields=ID,user_login,user_email,user_registered,roles # 查看最近注册用户 wp db query "SELECT ID,user_login,user_email,user_registered FROM wp_users ORDER BY user_registered DESC LIMIT 10;"如果存在短时间内新增管理员账号,需要继续查 wp_usermeta 中权限字段:wp db query "SELECT user_id,meta_key,meta_value FROM wp_usermeta WHERE meta_key IN ('wp_capabilities','wp_user_level') ORDER BY user_id DESC LIMIT 20;"技术分析WordPress Ajax 的核心入口是:/wp-admin/admin-ajax.php插件通常通过以下方式注册 Ajax 行为:add_action('wp_ajax_xxx', 'callback_function'); add_action('wp_ajax_nopriv_xxx', 'callback_function');其中 wp_ajax_nopriv_* 表示未登录用户也可访问。如果回调函数中执行了更新选项、创建用户、修改角色、调用 WooCommerce 管理逻辑等敏感操作,但没有做下面这些校验,就会形成权限绕过:current_user_can('manage_options') 或更细粒度能力检查缺失。check_ajax_referer() 缺失或 nonce 可被低权限用户获取。对传入参数直接进入内部控制器逻辑,形成方法调用链滥用。将前端组件请求与后台管理请求混用,导致权限边界失效。在授权验证时,不需要破坏业务数据。建议优先验证是否能触发目标 Ajax 分支、是否能越权调用敏感动作,而不是直接新增管理员账号。可以使用测试账号、临时环境或快照环境进行复现。操作步骤以下步骤适用于授权测试或自有环境排查。1. 确认插件安装与版本wp plugin list --status=active --fields=name,version,status | grep -E "elementor|woocommerce"如果没有 WP-CLI,也可以直接查文件:grep -i "Version" wp-content/plugins/elementor-pro/elementor-pro.php grep -i "Version" wp-content/plugins/woocommerce/woocommerce.php2. 检查 Ajax 动作注册点在插件目录中搜索 Ajax 注册和 nonce 校验:cd wp-content/plugins/elementor-pro grep -R "wp_ajax" -n . | head -50 grep -R "wp_ajax_nopriv" -n . | head -50 grep -R "check_ajax_referer\|current_user_can" -n modules/ | head -100重点看 WooCommerce、模板导入、站点设置、全局选项相关模块。如果发现某个回调函数存在 wp_ajax_nopriv 挂载,却没有权限检查,需要进一步追调用链。3. 低权限账号验证权限边界创建一个普通订阅者账号,仅用于确认接口是否被低权限触发:wp user create test_subscriber [email protected] --role=subscriber --user_pass='TestPass-ChangeMe-123'登录后获取 Cookie,然后请求可疑 Ajax 动作。这里用占位形式表示,实际动作名以代码审计结果为准:curl -i ' \ -H 'Cookie: wordpress_logged_in_xxx=YOUR_COOKIE' \ --data 'action=ELEMENTOR_PRO_RELATED_ACTION&_nonce=NONCE_IF_REQUIRED¶m=value'判断点:如果返回 0 或 -1,通常表示动作不存在、权限不足或 nonce 校验失败。如果返回 JSON 且进入业务逻辑,需要看是否发生状态变更。如果订阅者可以触发仅管理员应能执行的操作,基本可判定存在权限边界问题。4. 数据库侧确认是否发生敏感变更不要只看前端返回。WordPress 很多操作最终体现在 wp_options、wp_users、wp_usermeta 表中:# 最近变更的用户 wp db query "SELECT ID,user_login,user_email,user_registered FROM wp_users ORDER BY ID DESC LIMIT 10;" # 管理员角色用户 wp db query "SELECT u.ID,u.user_login,u.user_email,m.meta_value FROM wp_users u JOIN wp_usermeta m ON u.ID=m.user_id WHERE m.meta_key='wp_capabilities' AND m.meta_value LIKE '%administrator%';" # Elementor / WooCommerce 相关配置 wp db query "SELECT option_name,LENGTH(option_value) AS len FROM wp_options WHERE option_name LIKE '%elementor%' OR option_name LIKE '%woocommerce%' ORDER BY option_id DESC LIMIT 30;"日志留痕排查漏洞验证和应急排查都需要看 Web 访问日志。重点检索 admin-ajax.php、异常 action、短时间高频 POST 请求、异常 User-Agent。# Nginx 日志示例 grep "admin-ajax.php" /var/log/nginx/access.log | tail -100 grep "POST /wp-admin/admin-ajax.php" /var/log/nginx/access.log | awk '{print $1,$4,$7,$9,$12}' | tail -100 # 如果日志中记录了请求体,可进一步检索 action grep -i "elementor\|woocommerce\|admin-ajax" /var/log/nginx/access.log*Apache 环境:grep "admin-ajax.php" /var/log/apache2/access.log | tail -100 grep -i "POST /wp-admin/admin-ajax.php" /var/log/apache2/access.log*如果使用了 WAF、CDN 或反向代理,还要注意真实源 IP 是否在 X-Forwarded-For 中。Nginx 日志建议增加如下字段,方便后续追踪:log_format main_ext '$remote_addr $http_x_forwarded_for [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'rt=$request_time ua="$upstream_addr"';风险判断风险点影响排查位置低权限 Ajax 越权普通用户触发后台敏感操作插件 Ajax action、访问日志未认证 Ajax 暴露未登录用户可调用敏感接口wp_ajax_nopriv_* 注册点管理员账号被创建站点完全失陷wp_users、wp_usermeta插件配置被篡改页面注入、跳转、后门加载wp_options、主题模板文件修复建议立即升级 Elementor Pro、WooCommerce、WordPress Core 到官方修复版本。不要只升级 WordPress 核心,插件漏洞不会随核心自动消失。删除异常管理员账号,并重置所有管理员密码。检查 wp_users、wp_usermeta、wp_options、主题目录和插件目录是否存在异常写入。关闭不必要的用户注册功能,后台路径增加访问控制或二次认证。对 /wp-admin/admin-ajax.php 做行为监控,不建议简单封禁该入口,因为很多正常插件依赖它。检查服务器文件权限,避免 Web 用户对插件目录、主题目录有不必要的写权限。文件权限可参考:# 目录 755,文件 644 find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \; # wp-config.php 收紧权限 chmod 600 /var/www/html/wp-config.php # 确认属主,按实际 PHP-FPM 用户调整 chown -R www-data:www-data /var/www/html如果业务允许,可以在 Nginx 层对未登录的高风险 Ajax 请求做限制。示例仅供思路参考,实际不要直接复制到生产,需要结合插件 action 白名单测试:location = /wp-admin/admin-ajax.php { limit_req zone=ajax burst=20 nodelay; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/run/php/php8.1-fpm.sock; }代码层加固参考插件开发或二开时,Ajax 回调至少要包含 nonce 和能力检查。敏感操作不要只依赖前端隐藏按钮。add_action('wp_ajax_safe_update_option', 'safe_update_option_handler'); function safe_update_option_handler() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => 'permission denied'], 403); } check_ajax_referer('safe_update_option_nonce', 'nonce'); $value = isset($_POST['value']) ? sanitize_text_field($_POST['value']) : ''; update_option('custom_safe_option', $value); wp_send_json_success(['message' => 'updated']); }如果确实需要提供未登录 Ajax 接口,建议只处理无状态查询类逻辑,不要连接到用户创建、权限修改、插件安装、模板写入、站点选项更新等敏感能力。总结这类 WordPress 插件漏洞的关键不在于入口是否是 admin-ajax.php,而在于回调函数是否正确做了权限和 nonce 校验。授权测试时建议按“版本确认、代码定位、低权限验证、数据库核对、日志追踪、修复复测”的顺序推进,避免直接做破坏性验证。对生产站点来说,插件升级只是第一步。真正需要补上的,是异常账号清理、历史日志回溯、文件完整性检查和 Ajax 行为监控,否则很容易出现漏洞已修但后门仍在的情况。 网络请求、日志与边界流量分析示意
昨天 22:461天前 这个洞验证完建议别只停在“插件已升级”这一步,重点要确认有没有被利用过。Elementor Pro 这类问题常见利用链是通过 admin-ajax.php 修改站点关键 option,再注册/提升管理员,所以排查可以围绕 option 变更和新增管理员做。 可以先看访问日志里有没有相关 AJAX action 和敏感 option: grep -R "admin-ajax.php" /var/log/nginx/*access* | grep -Ei "elementor|woocommerce|update_page_option|users_can_register|default_role" grep -R "admin-ajax.php" /var/log/apache2/*access* | grep -Ei "elementor|woocommerce|update_page_option|users_can_register|default_role" 如果用了 WP-CLI,直接查当前关键配置: wp option get users_can_register wp option get default_role wp option get siteurl wp option get home 正常情况下多数站点应该是: users_can_register = 0 default_role = subscriber 如果发现 default_role 被改成 administrator,或者 users_can_register 被打开过,就要继续查用户表: wp user list --role=administrator --fields=ID,user_login,user_email,user_registered wp user list --orderby=registered --order=DESC --fields=ID,user_login,user_email,user_registered,roles 数据库里也可以直接看: SELECT ID,user_login,user_email,user_registered FROM wp_users ORDER BY user_registered DESC LIMIT 20; SELECT user_id,meta_key,meta_value FROM wp_usermeta WHERE meta_key LIKE '%capabilities%' AND meta_value LIKE '%administrator%'; 修复动作建议按这个顺序做: Elementor Pro 升到官方修复版本以上,WooCommerce、Elementor Free 也一起更新。 确认关闭注册和默认角色: wp option update users_can_register 0 wp option update default_role subscriber 删除异常管理员账号,重置所有管理员密码。 检查是否有新装的可疑插件、主题或 mu-plugin: wp plugin list wp theme list find wp-content/mu-plugins -type f -maxdepth 2 -ls 2>/dev/null find wp-content/uploads -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) -ls 轮换 wp-config.php 里的 salts,强制所有会话失效。 另外可以临时在 WAF/Nginx 层对异常请求做拦截,比如包含敏感 option 修改的请求直接拒绝: location = /wp-admin/admin-ajax.php { if ($request_body ~* "(users_can_register|default_role|administrator)") { return 403; } include fastcgi_params; fastcgi_pass php-fpm; } 这个规则只能作为临时缓解,不建议长期依赖。最终还是要升级插件并确认站点没有遗留后门。对于这类权限绕过,最容易漏的是“攻击者已经创建了管理员,但漏洞补上后账号还在”,所以用户和 option 的核查一定要做。
创建帐户或登录后发表意见