CVE-2026–41505:一个两字母的导入如何破坏开源LMS的认证安全

admin 2026-04-29 05:03:13 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2026-41505是RELATE开源课程管理系统中的高危漏洞(CVSS8.7),因在密码重置令牌和考试凭证生成中使用非加密安全的Pythonrandom模块(MersenneTwister),导致攻击者可通过约156次请求恢复伪随机数状态,预测未来令牌并实现账户接管。关键发现包括SHA-1哈希无法弥补弱随机数输入的可预测性,修复方案为使用secrets模块生成加密安全随机数。 综合评分: 87 文章分类: 漏洞分析,WEB安全,应用安全,安全开发,解决方案


cover_image

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 的认证安全》

评论:0   参与:  0