WordPress AI Engine信息泄露漏洞 | CVE-2025-11749 复现&研究

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、漏洞位置

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 tokenREST路由
  • 例如:/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 修复建议

修复方案

  1. 升级到最新版本:升级到最新版本:ai-engine

  2. 临时防护措施:
    禁用"无认证 URL"功能 :若非必需,可以关闭插件中"无认证 URL"选项,减少攻击面
    启用 WAF/IPS 规则 :拦截对/wp-json/mcp/v1端点的异常访问请求
    关注用户异常变动:目前公开的POC均是添加高权限用户,可重点关注账户

免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。

相关推荐
_妲己2 小时前
stable diffusion的MLSD直线(AI室内设计)
人工智能·stable diffusion
FF-Studio2 小时前
Ubuntu 24.04 磁盘爆满“灵异“事件:Btrfs, Snapper 与删不掉的空间
linux·运维·人工智能·ubuntu
2401_841495642 小时前
【自然语言处理】关系性形容词的特征
人工智能·python·自然语言处理·自动识别·特征验证·关系性形容词·语言学规则和计算
rebekk2 小时前
Hydra介绍
人工智能·python
我不是小upper2 小时前
从理论到代码:随机森林 + GBDT+LightGBM 融合建模解决回归问题
人工智能·深度学习·算法·随机森林·机器学习·回归
Faker66363aaa2 小时前
CornerNet-Hourglass104生产线检测与分类-1模型训练与部署
人工智能·分类·数据挖掘
YANshangqian2 小时前
高性能AI聊天工具
人工智能
donecoding2 小时前
前端AI开发:为什么选择SSE,它与分块传输编码有何不同?axios能处理SSE吗?
前端·人工智能