0x0 背景介绍
WordPress的AI Engine插件在≤ 3.1.3版本中,通过/mcp/v1/ REST API端点存在敏感信息泄露漏洞。当启用"No-Auth URL"时,该端点会暴露"Bearer Token"值。这使得未经身份验证的攻击者能够提取Bearer Token,从而获取有效会话的访问权限,并执行诸如创建新管理员账户等多项操作,导致权限提升。
0x1 环境搭建
1、Ubuntu24+Docker搭建配置
- 另存为
install.sh并赋予执行权限chmod +x install.sh
bash
#!/bin/bash
# 检查 unzip 是否安装
if ! command -v unzip &> /dev/null; then
echo "[*] 未检测到 unzip,正在安装..."
apt update && apt install -y unzip wget curl
echo "[+] unzip 安装完成[+]"
fi
echo "[*] 阶段1/5:创建漏洞复现专用目录... "
mkdir -p vuln-ai-engine && cd vuln-ai-engine || { echo "❌ 创建目录失败"; exit 1; }
echo "[+] 工作目录: $(pwd)[+] "
echo "[*] 阶段2/5:生成 docker-compose.yml..."
cat > docker-compose.yml <<EOF
services:
db:
image: mysql:5.7
container_name: aiengine-db
environment:
MYSQL_ROOT_PASSWORD: vuln-root-pass
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: vuln-user-pass
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 10
wordpress:
image: wordpress:php7.4-apache
container_name: aiengine-wp
ports:
- "8086:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: vuln-user-pass
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html/wp-content
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 15s
timeout: 10s
retries: 6
entrypoint: ["/bin/bash", "-c", "docker-entrypoint.sh apache2-foreground"]
volumes:
db_data:
wp_data:
EOF
echo "[*] 阶段3/5:启动漏洞复现环境... "
docker compose up -d
# 等待服务启动
echo "[*] 等待服务启动 (约60秒)... "
for i in {1..12}; do
echo -n "."
sleep 5
if [ $i -eq 6 ]; then
echo -ne " 50%"
fi
done
echo -e "\n[√] 服务启动完成!"
# 等待 WordPress 安装页面就绪
echo "[*] 等待 WordPress 就绪... "
until [ $(curl -s -w %{http_code} -o /dev/null http://localhost:8086/wp-admin/install.php) -eq 200 ]; do
echo -n "."
sleep 2
done
echo -e "\n[+] 服务已就绪[+] "
echo "[*] 阶段4/5:安装 AI Engine 插件 (v3.1.2)[*] "
PLUGIN_URL="https://downloads.wordpress.org/plugin/ai-engine.3.1.2.zip"
PLUGIN_ZIP="ai-engine.3.1.2.zip"
EXTRACT_TMP="ai-engine-extract"
# 清理
rm -rf "$EXTRACT_TMP" ai-engine
# 下载
if ! wget -q "$PLUGIN_URL" -O "$PLUGIN_ZIP"; then
echo "[-] 下载失败,尝试备用镜像...[-]"
if ! wget -q "https://mirror.ghproxy.com/$PLUGIN_URL" -O "$PLUGIN_ZIP"; then
echo "[!] 插件下载失败"
exit 1
fi
fi
# 解压
unzip -q "$PLUGIN_ZIP" -d "$EXTRACT_TMP"
# 获取内部目录(如 ai-engine-3.1.2)
INNER_DIR=$(find "$EXTRACT_TMP" -mindepth 1 -maxdepth 1 -type d | head -n1)
if [ ! -d "$INNER_DIR" ]; then
echo "[-] 解压结构异常,未找到插件目录"
exit 1
fi
# 重命名为标准插件名
mv "$INNER_DIR" ai-engine
# 复制进容器
docker cp ai-engine aiengine-wp:/var/www/html/wp-content/plugins/
# 清理本地
rm -rf "$EXTRACT_TMP" "$PLUGIN_ZIP" ai-engine
# 验证
if docker exec aiengine-wp test -f /var/www/html/wp-content/plugins/ai-engine/ai-engine.php; then
echo "[+] AI Engine 插件部署成功![+]"
else
echo "[-] 插件主文件缺失,部署失败[-] "
exit 1
fi
echo "=============================================="
echo "√ CVE-2025-11749 漏洞复现环境部署完成!"
echo " - 站点标题: CVE-2025-11749"
echo " - 用户名: admin"
echo " - 密码: 默认强密码"
echo " - 电子邮箱: cve-2025-11749@local.test"
echo
echo " 安装后登录后台 → 插件 → 启用 'AI Engine'"
echo " 进入 AI Engine 设置 → 启用 'Unauthenticated URLs' 功能"
echo " Meow Apps->AI Engine->Settings->Remote Access选项"
echo " 启用SSE Endpoint、No-Auth URL、Tuned Core"
2、 环境安装成功后,手动启用插件再开启插件配置:

0x2 漏洞复现
1、Xray-xpoc检测
bash
https://github.com/Kai-One001/cve-/blob/main/WordPress_AI_Engine_CVE-2025-11749.yml
2、复现截图
- 没有实现直接创建账户的操作哦

3、手动复现步骤(发现共有三个接口可利用创建用户)
-
0、先查询当前用户,确认只有一个账户

-
1、先无认证获取值

-
2.1、利用姿势-A:无认证创建用户(
messages接口)

-
2.2、利用姿势-B:认证方式创建用户(标准方式)
-
先根据
sse接口获取有效认证

-
根据获取的认证创建用户

-
2.3、利用姿势-C:无认证创建用户(
SSE)

添加的账户可登录,举例:

-
3、其它利用姿势-更新账户权限
-
先创建非管理员账户一个

-
更新权限(自行考虑,如果ID错误,会导致无法登录)

-
更新权限后查看用户权限

-
错误更新ID后,正常用户登录失效

-
用户ID查看办法(一种数据库、一种是登录后看下链接如下)

4、复现流量特征 (PCAP)
大部分都是明文的,挑几个重点说
1、获取敏感信息

2、认证方式创建用户(标准方式)

3、无认证创建用户(SSE)

4、更新用户权限

0x3 漏洞原理分析
1、漏洞位置
- 从官方发布的漏洞代码中, 锁定文件
mcp.php:plugins.trac.wordpress.org-ai-engine-mcp.php
2、漏洞入口
- 公告中
"No-Auth URL"功能,(怪不的大厂要求注释率呢,一下就找到了)定位到mcp_noauth_url中
php
// No-Auth URL endpoints (with token in path)
$noauth_enabled = $this->core->get_option( 'mcp_noauth_url' );
if ( $noauth_enabled && !empty( $this->bearer_token ) ) {
register_rest_route( $this->namespace, '/' . $this->bearer_token . '/sse', [
'methods' => 'GET',
'callback' => [ $this, 'handle_sse' ],
'permission_callback' => function ( $request ) {
return $this->handle_noauth_access( $request );
},
] );
register_rest_route( $this->namespace, '/' . $this->bearer_token . '/sse', [
'methods' => 'POST',
'callback' => [ $this, 'handle_sse' ],
'permission_callback' => function ( $request ) {
return $this->handle_noauth_access( $request );
},
] );
register_rest_route( $this->namespace, '/' . $this->bearer_token . '/messages', [
'methods' => 'POST',
'callback' => [ $this, 'handle_message' ],
'permission_callback' => function ( $request ) {
return $this->handle_noauth_access( $request );
},
] );
}
}
- 如果管理员启用了
"MCP No-Auth URL"(默认是关闭的) - 插件会动态注册一个包含完整
bearer token的REST路由 - 例如:
/wp-json/mcp/v1/abc123xyz/sse - 其中
abc123xyz就是你的静态Bearer Token
3、权限校验被绕过
当请求 /mcp/v1/你的token/sse 这个路径时,WordPress会先调用handle_noauth_access($request)来检查权限。
php
'permission_callback' => function ( $request ) {
return $this->handle_noauth_access( $request );
},
那查看handle_noauth_access函数
php
public function handle_noauth_access( $request ) {
// For no-auth URLs, the token is already verified by being in the URL path
// Double-check that the route actually contains the token
$route = $request->get_route();
if ( strpos( $route, '/' . $this->bearer_token . '/' ) === false ) {
if ( $this->logging ) {
error_log( '[AI Engine MCP] ❌ Invalid no-auth URL access attempt.' );
}
return false;
}
// Set the current user to admin since token is valid
if ( $admin = $this->core->get_admin_user() ) {
wp_set_current_user( $admin->ID, $admin->user_login );
}
return true;
}
- 从请求的
URL路径中提取信息 - 验证路径里是否包含配置好的
bearer_token - 如果包含,就认为"认证成功",并把当前用户设为管理员
能做什么呢?
MCP的核心功能是通过tools/call调用WordPress内部工具,列出如下:
php
#### 1.1 用户管理工具
- `wp_get_users`: 获取用户列表
- `wp_create_user`: **创建用户(可指定为管理员)**
- `wp_update_user`: **更新用户(可提升权限)**
#### 1.2 内容管理工具
- `wp_create_post`: 创建文章/页面
- `wp_update_post`: 修改文章/页面
- `wp_delete_post`: 删除文章/页面
- `wp_get_post`: 获取文章内容
#### 1.3 系统管理工具
- `wp_get_option`: 获取 WordPress 选项
- `wp_update_option`: **修改 WordPress 选项**
- `wp_list_plugins`: 列出已安装插件
#### 1.4 媒体管理工具
- `wp_upload_media`: **上传文件(可以研究下,我没看)**
- `wp_delete_media`: 删除媒体文件
0x4 修复建议
修复方案
-
升级到最新版本:升级到最新版本:ai-engine
-
临时防护措施:
禁用"无认证 URL"功能 :若非必需,可以关闭插件中"无认证 URL"选项,减少攻击面
启用 WAF/IPS 规则 :拦截对/wp-json/mcp/v1端点的异常访问请求
关注用户异常变动:目前公开的POC均是添加高权限用户,可重点关注账户
免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。