关注公众号回复“漏洞”获取研究环境或工具
漏洞信息
前面公众号已经发表了2篇关于Moodle Shibboleth PHP反序列化漏洞及利用链构造的分析文章:
CVE-2021-36394-Moodle RCE漏洞分析及PHP反序列化利用链构造之旅
QCyber,公众号:且听安全CVE-2021-36394-Moodle RCE漏洞分析及PHP反序列化利用链构造之旅
CVE-2021-36394-Moodle Shibboleth PHP反序列化利用链构造之二
QCyber,公众号:且听安全CVE-2021-36394-Moodle Shibboleth PHP反序列化利用链构造之二
今天带来第3篇,这是一个session会话劫持漏洞,漏洞信息如下:
当Moodle开启Shibboleth认证时,存在用户session劫持风险,可导致认证绕过和身份劫持。经过分析发现漏洞是由于Moodle Shibboleth 认证的`Database session driver`会话机制存在比较严重的逻辑缺陷导致的,`Database session driver`这种配置方式在Moodle二次开发中也比较常见。
环境构建
最近很多小伙伴在后台私信我关于漏洞复现的问题,下面简单介绍下如何构建这个漏洞的分析环境。程序下载地址:
moodle v3.11.2
https://download.moodle.org/download.php/stable311/moodle-3.11.2.tgz
为了方便调试,可以在`php.ini`中加入xdebug配置。安装完毕后,登录后台进入`Manage authentication`,开启`Shibboleth`:
前面已经讲到,要触发该漏洞,还需要修改session会话处理方式为`Database session driver`,在`config.php`中加入如下配置:
漏洞分析
漏洞触发的原理比较简单。我们在以前公众号文章中已经讲过,`moodleauthshibbolethlogout.php`定义了一个WSDL请求:
`LogoutNotification`接口的处理函数如下:
当以`dbsession`处理session会话时,将调用`logout_db_session`:
首先从数据库中提取全部的session会话信息赋值给`$sessions`,然后通过一个`for`循环逐个执行`kill_user_sessions`,销毁session会话。回顾从数据库提取session的过程,这里通过`session_decode`函数完成处理:
`session_decode`对函数参数序列化的会话数据进行解码,并且使用解码后的数据填充`$_SESSION`超级全局变量。也就是说,全局session变量被赋值为最后一个处理的session值,这就导致了session会话劫持。
我们可以首先利用admin用户登录Moodle后台,然后构造一个新的未授权请求对象发送WSDL请求,这样就可以劫持admin用户权限。
修复方式
`moodleauthshibbolethclasseshelper.php`中的`logout_db_session`函数发生了变化:
删除了php自带的`session_decode`,换成自定义的函数`unserializesession`进行处理:
/**
* Unserialize a session string.
*
* @param string $serializedstring
* @return array
*/
private static function unserializesession($serializedstring) {
$variables = array();
$index = 0;
// Find next delimiter after current index. It's key being the characters between those points.
while ($delimiterpos = strpos($serializedstring, '|', $index)) {
$key = substr($serializedstring, $index, $delimiterpos - $index);
// Start unserializing immediately after the delimiter. PHP will read as much valid data as possible.
$value = unserialize(substr($serializedstring, $delimiterpos + 1),
['allowed_classes' => ['stdClass']]);
$variables[$key] = $value;
// Advance index beyond the length of the previously captured serialized value.
$index = $delimiterpos + 1 + strlen(serialize($value));
}
return $variables;
}
}
这样就不能给全局变量`$_SESSION`进行赋值了。
由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,且听安全团队及文章作者不为此承担任何责任。
点关注,不迷路!
关注公众号回复“漏洞”获取研究环境或工具
原文始发于微信公众号(且听安全):【最新漏洞预警】CVE-2021-40691 Moodle Shibboleth未授权session会话劫持漏洞