在网络安全的世界里,每一个漏洞都可能成为攻击者突破防线的入口。最近,Quarkslab的安全研究人员在对Moodle(一款广泛使用的开源学习管理系统)进行审计时[1],发现了一个严重的逻辑漏洞,该漏洞允许攻击者绕过所有限制,利用SSRF(服务器端请求伪造)漏洞。这一发现不仅揭示了Moodle在安全防护上的薄弱环节,也提醒了我们对逻辑漏洞的重视。今天,我们将深入探讨这一漏洞的细节,以及它是如何被发现和利用的。
calendar/import.php
moodleform->get_data() (formslib.php)
-
moodleform->is_validated() (formslib.php)
-
moodleform->validate_defined_fields() (formslib.php)
-
core_calendarlocaleventformsmanagesubscriptions->validation() (calendar/classes/local/event/forms/managesubscriptions.php)
-
calendar_get_icalendar() (calendar/lib.php)
-
curl::get() (lib/filelib.php)
-
curl::request() (lib/filelib.php)
-
curl::check_securityhelper_blocklist() (lib/filelib.php)
-
curl_security_helper::url_is_blocked() (lib/classes/files/curl_security_helper.php)
-
curl_security_helper::host_is_blocked() (lib/classes/files/curl_security_helper.php)
-
curl_security_helper::host_explicitly_blocked() (lib/classes/files/curl_security_helper.php)
-
curl_security_helper::get_host_list_by_name() (lib/classes/files/curl_security_helper.php)
-
gethostbynamel()
-
curl_security_helper::address_explicitly_blocked() (lib/classes/files/curl_security_helper.php)
-
curl_exec()
localhost(127.0.0.1)
发送请求。
文件:calendar/import.php
<?php...$formdata = $form->get_data();...
文件:lib/formslib.php
函数:moodleform::get_data()
<?php...phpabstract class moodleform { ... function get_data() { $mform =& $this->_form; if (!$this->is_cancelled() and $this->is_submitted() and $this->is_validated()) { ... } else { return NULL; } } ...}...
文件:lib/formslib.php
函数:moodleform::is_validated()
文件:lib/formslib.php
函数:moodleform::validate_defined_fields()
文件:calendar/classes/local/event/forms/managesubscriptions.php
函数:core_calendarlocaleventformsmanagesubscriptions::validation()
从下面的代码中可以看到,当执行calendar_get_icalendar()函数时,用户提供的URL会被作为参数传递给curl对象。
文件:calendar/lib.php
函数:calendar_get_icalendar()
让我们更深入地研究代码以了解发生了什么。
文件:lib/filelib.php
函数:curl::get()
在通过curl_exec()实际执行请求之前,会进行一些检查。
文件:lib/filelib.php
函数:curl::request()
以下每一个步骤都经过了分析,以确定如何绕过Moodle的安全机制。
文件:lib/filelib.php
函数:curl::check_securityhelper_blocklist()
url_is_blocked()
中:
文件:lib/classes/files/curl_security_helper.php
函数:curl_security_helper::url_is_blocked()
host_is_blocked()
:
文件:lib/classes/files/curl_security_helper.php
函数:curl_security_helper::host_is_blocked()
host_explicitly_blocked()
中:
文件:lib/classes/files/curl_security_helper.php
函数:curl_security_helper::host_explicitly_blocked()
get_host_list_by_name()
:
可以观察到,与URL中存在的域名相关联的IP地址解析是通过gethostbynamel()函数进行的。
文件:lib/classes/files/curl_security_helper.php
函数:curl_security_helper::get_host_list_by_name()
该函数返回的IP或多个IP随后会被与一个黑名单进行比对。
address_explicitly_blocked()
中:
文件:lib/classes/files/curl_security_helper.php
函数:curl_security_helper::address_explicitly_blocked()
阅读了所有这些代码后,我们能够确认可以利用该代码逻辑,因为在调用gethostbynamel()函数和调用curl_exec()函数之间存在一个利用窗口(时间窗口),从而导致了一个TOC-TOU漏洞。
为了利用此漏洞,可以使用以下形式的URL:
-
http://<DOMAIN_UNDER_OUR_CONTROL>/AAAA?BBBB=CCCC
(HTTP) -
https://<DOMAIN_UNDER_OUR_CONTROL>/AAAA?BBBB=CCCC
(HTTPS)
但审计还揭示了可以使用以下形式的URL:
-
webcal://<DOMAIN_UNDER_OUR_CONTROL>/AAAA?BBBB=CCCC
(HTTP)
因为处理程序webcal://会自动替换为http://,如下面的代码所示。
文件:calendar/classes/local/event/forms/managesubscriptions.php
功能:core_calendarlocaleventformsmanagesubscriptions::strip_webcal()
<?php...classmanagesubscriptions{ ...publicfunctiondefinition_after_data(){ $mform =& $this->_form; $mform->applyFilter('url', static::class . '::strip_webcal'); $mform->applyFilter('url', 'trim'); }publicstaticfunctionstrip_webcal($url){if (strpos($url, 'webcal://') === 0) { $url = str_replace('webcal://', 'http://', $url); }return $url; }...}...
图注:漏洞利用日历功能
图注:左侧是来自Web服务器(Moodle实例)的HTTP日志视图,右侧是恶意DNS服务器(托管在C2上)的视图。
为支持作者自身的发现,作者还演示了如何利用文件选择器(File picker)功能,并通过SSRF发起的请求获取目标响应。
Moodle文件选择器中的“URL下载器”功能允许用户从外部URL添加文件,而不是直接从本地计算机上传文件。文件选择器是一个工具,允许用户(如教师、管理员、学生等)将文件上传到Moodle中,例如,用于添加文件到活动、资源或作业中。通常情况下,它允许你从本地计算机选择文件,或浏览 Moodle的文件系统。
URL下载器允许用户输入一个图片的URL(任何类型,例如png、jpg)以将该图片复制到Moodle中。此外,通过输入网页地址,该功能还可以用于获取整个网页中的所有图片。
图注:使用文件选取器功能第1部分
图注:使用文件选取器功能第2部分
图注:使用文件选取器功能第3部分
假设在托管Moodle的Web服务器根目录下(例如一个AWS实例),存在像aaaa.json或phpinfo.php这样的文件(例如在镜像sprintcube/docker-compose-lamp的Web根目录中常见的文件)。
为了利用这一功能,作者在自己的C2(命令与控制服务器)上托管一个test.html文件(HTML格式)。攻击者向Moodle指定一个HTML文件的URL,供其解析(以便Moodle提取其中的图片标签)。
<html><imgsrc="http://poc.ns.<DOMAIN_UNDER_OUR_CONTROL>/aaaa.json"></html>
图注:由Moodle下载和解析的C2上公开的HTML文件
攻击者要求Moodle下载该HTML文件中识别出的图片。
图注:Moodle向URLhttp://poc.ns.<DOMAIN_UNDER_OUR_CONTROL>/phpinfo.php发送GET请求
攻击者通过SSRF获取Moodle发送的HTTP GET请求的响应内容。
图注:攻击者检索的响应内容
正如从Moodle Web服务器日志和C2服务器日志中所见,SSRF漏洞已被成功利用。
图注:左侧是Moodle Web服务器日志,右侧是C2日志
如果文件test.html包含以下内容:
文件:test.html(托管在C2上)
<html><imgsrc="http://poc.ns.<DOMAIN_UNDER_OUR_CONTROL>/phpinfo.php"></html>
将采取以下步骤。
图注:由Moodle下载和解析的C2上公开的HTML文件
图注:Moodle向URLhttp://poc.ns.<DOMAIN_UNDER_OUR_CONTROL>/phpinfo.php发送GET请求
图注:攻击者检索的响应内容
图注:左侧是Moodle Web服务器日志,右侧是C2日志
因此,非常重要的一点是,如果Moodle托管在AWS上(通过IMDSv1),该漏洞可以被利用来实现远程代码执行(RCE)。
if TOC_TOU_CHECK % 3 == 0:
文件:server.py[3]
漏洞利用(流氓DNS)
原文始发于微信公众号(山石网科安全技术研究院):学习管理系统Moodle核心代码安全审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论