文章总结: CVE-2026-41505是RELATE开源课程管理系统中的高危漏洞(CVSS8.7),因在密码重置令牌和考试凭证生成中使用非加密安全的Pythonrandom模块(MersenneTwister),导致攻击者可通过约156次请求恢复伪随机数状态,预测未来令牌并实现账户接管。关键发现包括SHA-1哈希无法弥补弱随机数输入的可预测性,修复方案为使用secrets模块生成加密安全随机数。 综合评分: 87 文章分类: 漏洞分析,WEB安全,应用安全,安全开发,解决方案
CVE-2026–41505:一个两字母的导入如何破坏开源 LMS 的认证安全
haidragon haidragon
安全狗的自我修养
2026年4月28日 12:26 中国香港
在小说阅读器读本章
去阅读
官网:http://securitytech.cc
CVE: CVE-2026–41505 严重性: 高(CVSS 8.7) CWE: CWE-338 —— 使用加密学上不安全的伪随机数生成器 公告:https://github.com/inducer/relate/security/advisories/GHSA-rvx5-95mm-p77v 项目: RELATE —— 开源课程管理系统 作者: Ruslan Amrahov
按回车或点击查看大图
CVE-2026–41505
引言
2026 年 4 月,我在 RELATE(一个由伊利诺伊大学 Andreas Kloeckner 开发的开源课程管理系统)中发现了一个安全漏洞。漏洞的根源仅仅是一行 Python 代码:
importrandom
两个单词,一个导入。但在安全敏感的上下文中,这足以让密码重置令牌、邮箱登录链接以及考试凭证代码暴露在可预测攻击之下。
本文将从技术角度讲解我是如何发现该漏洞的、它为何重要,以及它为什么是真正可利用的。
什么是 RELATE?
RELATE(Relates Educational Activities to Technology in Education)是一个基于 Django 的学习管理系统,被高校用于提供测验、流程式评估和课程材料。它是开源项目,并可通过 pip 安装(relate-courseware)。
漏洞代码
位置 1:course/auth.py — make_sign_in_key()
def make_sign_in_key(user:User) ->str:
importhashlib
importrandom #←MersenneTwister,不是加密安全的
from timeimporttime
m=hashlib.sha1()
m.update(user.email.encode("utf-8"))
m.update(hex(random.getrandbits(128)).encode()) # ← 可预测
m.update(str(time()).encode("utf-8"))
returnm.hexdigest()
该函数用于生成以下用途的令牌:
- 邮件发送的密码重置链接
- 邮箱登录(魔法链接)
- API 认证令牌
位置 2:course/exam.py — gen_ticket_code()
ticket_alphabet="ABCDEFGHJKLPQRSTUVWXYZabcdefghjkpqrstuvwxyz23456789"
def gen_ticket_code():
from randomimportchoice#←PRNG,不是CSPRNG
return"".join(choice(ticket_alphabet) for_i inrange(8))
该函数生成 8 位考试访问码。
为什么 random 在这里是错误的工具
Python 的 random 模块基于 Mersenne Twister(梅森旋转算法),是一种伪随机数生成器(PRNG),适用于统计模拟和一般随机用途。
优点:快速、分布良好、测试充分 致命问题:不具备加密安全性
核心问题:状态重建
Mersenne Twister 内部维护一个 624 × 32 位整数 的状态(总计 19968 位)。
关键性质:
如果攻击者能观察到连续的 624 个 32 位输出,就可以完全恢复内部状态,并 100% 预测之后的所有输出。
这不是理论问题,而是已被广泛验证的事实,且已有现成攻击库。
SHA-1 能拯救吗?
make_sign_in_key() 使用 SHA-1 混合以下数据:
m.update(user.email.encode("utf-8")) # 攻击者已知
m.update(hex(random.getrandbits(128)).encode()) # 状态恢复后可预测
m.update(str(time()).encode("utf-8")) # 可估算
分析:
| 输入 | 攻击者掌握情况 | | — | — | | user.email | 已知(攻击者可触发重置) | | random.getrandbits(128) | 状态恢复后可预测 | | time() | 可通过响应时间估算 |
一旦 MT 状态被恢复,攻击者只需枚举一个较小时间窗口(几秒内),即可暴力计算对应 SHA-1,搜索空间远小于理论的 2^160。
攻击流程
阶段 1:恢复 MT 状态
攻击者创建多个账号并反复触发密码重置:
- 每次调用
getrandbits(128)会产生 4 个 32 位输出 - 需要 624 个输出恢复状态
156 次请求 × 4 =624→ 完整状态恢复
阶段 2:预测令牌
恢复状态后:
- 可预测所有未来
random.getrandbits(128)输出 - 结合 HTTP 响应头中的时间估算
- 可计算任意用户的未来 token
阶段 3:账户接管
1. 攻击者触发 [email protected] 的密码重置
2. 服务器生成 token
3. 攻击者已知随机数
4. 估算时间
5. 计算 SHA-1(email+random+time)
6. 使用预测 token 重置密码
7. 完整接管账户
考试凭证预测
理论熵:log2(51^8) ≈ 45.6 bits
本身就不高。一旦 MT 状态恢复:
→ 所有未来考试码都可预测 → 可非法进入考试
CVSS 评分为何为 8.7(高危)
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:H/A:H
解释:
- AV:N → 可通过网络攻击
- AC:H → 需要一定复杂度(约 156 次请求)
- PR:N → 无需权限
- UI:N → 无需用户交互
- S:C → 影响范围改变(可攻击其他用户)
- C:N → 无直接机密泄露
- I:H → 完整性高影响(账号接管)
- A:H → 可影响系统可用性(考试中断)
关键点:Scope Changed(跨用户攻击)
修复方案
使用 Python 的 secrets 模块替代 random。
修复 1:make_sign_in_key()
# 修复前
importrandom
from timeimporttime
m=hashlib.sha1()
m.update(user.email.encode("utf-8"))
m.update(hex(random.getrandbits(128)).encode())
m.update(str(time()).encode("utf-8"))
returnm.hexdigest()
# 修复后
importsecrets
returnsecrets.token_hex(32)
说明:
- 32 字节 = 256 位安全随机数
- 来自操作系统 CSPRNG
- 无内部状态可恢复
修复 2:gen_ticket_code()
# 修复前
from randomimportchoice
return"".join(choice(ticket_alphabet) for_i inrange(8))
# 修复后
importsecrets
return"".join(secrets.choice(ticket_alphabet) for_ inrange(8))
secrets.choice() 可直接替换 random.choice(),但具备加密安全性。
时间线
2026-04-16 — 发现漏洞
2026-04-16 — 提交报告
2026-04-18 — 官方确认并修复
2026-04-18 — 发布安全公告
2026-04-18 — 分配 CVE
修复用时:48 小时
经验总结
1. 安全场景中 import random 是危险信号
官方文档明确说明:
不应用于安全用途,应使用 secrets 模块
2. 组合不等于安全
弱 PRNG + SHA-1 ≠ 安全 输入可预测 → 输出仍可预测
3. 一个问题往往不止一处
发现一个点 → 必须全局搜索同类用法
4. 负责任披露是有效的
48 小时从报告到修复,说明开源安全响应是有效的。
总结
CVE-2026–41505 是 CWE-338 的典型案例:在安全敏感场景中使用了弱伪随机数生成器。
修复只需两行代码,但如果被利用,可能导致全球所有 RELATE 实例被批量接管账户。
安全的本质不是复杂,而是:在正确的地方使用正确的工具。
-
random→ 用于模拟
-
secrets→ 用于安全
-
-
公众号:安全狗的自我修养
-
vx:2207344074
-
http://gitee.com/haidragon
-
http://github.com/haidragon
-
bilibili:haidragonx
-
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全狗的自我修养 haidragon haidragon《CVE-2026–41505:一个两字母的导入如何破坏开源 LMS 的认证安全》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论