关注公众号回复“漏洞”获取研究环境
Moodle(Modular Object-Oriented Dynamic Learning Environment)是一个用于制作网络课程或网站的软件包,在全球范围内使用广泛。
前面公众号分享的Moodle漏洞分析文章如下:
CVE-2021-36394
QCyber,公众号:且听安全CVE-2021-36394-Moodle RCE漏洞分析及PHP反序列化利用链构造之旅
CVE-2021-36394
QCyber,公众号:且听安全CVE-2021-36394-Moodle Shibboleth PHP反序列化利用链构造之二
CVE-2021-40691 Qcyber,公众号:且听安全【最新漏洞预警】CVE-2021-40691 Moodle Shibboleth未授权session会话劫持漏洞
Moodle官网通报:
CVE-2022-0332 https://moodle.org/mod/forum/discuss.php?d=431099
从通报信息来看,漏洞触发点位于Moodle h5p web service中,为了便于漏洞分析,首先我们完成Moodle web services以及h5p插件的配置。
开启web services,并开启`REST protocol`协议:
为用户配置访问Token:
最后创建一个`course`,然后添加一个h5p资源:
定位Moodle REST Web服务的入口文件`/webservice/rest/server.php`:
首先判断是否开启了REST服务协议,这也是在环境准备时必须开启`REST protocol`协议的原因。继续往下走:
实例化`webservice_rest_server`对象,然后通过`run`启动,进入:
这里完成了3个操作:
##0x01 parse_request
`parse_request`函数定义如下:
主要完成对参数的检查,从上面可以看出,合法参数名称如下:
moodlewsrestformat
wsusername
wspassword
wsfunction
wstoken
...
##0x02 authenticate_user
`authenticate_user`定义如下:
通过REST Web服务接口访问时,`$this->authmethod`取值为`WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN`,认证过程如下:
通过查询数据库,检查`$this->token`(来源于请求参数`wstoken`)是否合法,如果认证通过,将返回用户对象`$user`。
##0x03 load_function_info
`load_function_info`定义如下:
首先判断`$this->functionname`(来源于请求参数`wsfunction`)是否为空,接着调用`external_api::external_function_info`函数提取处理函数信息:
查询数据表`mdl_external_functions`(默认前缀为`mdl_`,取决于程序安装配置),根据`$function`获取REST请求对应处理的类和函数。`mdl_external_functions`表中一共有617个接口定义:
CVE-2022-0332漏洞触发的接口如下所示:
接口名称`mod_h5pactivity_get_user_attempts`,对应的处理为`mod_h5pactivityexternalget_user_attempts`类的`execute`函数:
从上面的函数定义可以看出,请求可以携带`page`、`perpage`、`h5pactivityid`、`sortorder`等参数。
为了方便调试分析,参考前面的分析,我们构造请求如下:
/moodle/webservice/rest/server.php?wstoken=***&wsfunction=mod_h5pactivity_get_user_attempts&moodlewsrestformat=json&h5pactivityid=3&sortorder=123'
顺利进入`execute`函数:
继续往下走,第122行调用`get_active_users`函数获取用户信息:
跟进:
此时查询的`$sql`语句为:
显然对`sortorder`取值没有进行任何过滤,直接拼接进入了SQL查询语句,看下最终的SQL查询语句如下:
SELECT DISTINCT u.id, u.firstname, u.lastname
FROM mdl_user u JOIN mdl_user_enrolments ej1_ue ON ej1_ue.userid = u.id
JOIN mdl_enrol ej1_e ON (ej1_e.id = ej1_ue.enrolid AND ej1_e.courseid = '2')
JOIN (SELECT DISTINCT userid
FROM mdl_role_assignments
WHERE contextid IN (1,3,26,30)
AND roleid IN (6,5,4,3,1)
) ra ON ra.userid = u.id
LEFT JOIN (SELECT DISTINCT userid
FROM mdl_role_assignments
WHERE contextid IN (1,3,26,30)
AND roleid IN (3,1)
) reviewer ON reviewer.userid = u.id
WHERE 1 = 1 AND u.deleted = 0 AND u.id <> '1' AND u.deleted = 0 AND reviewer.userid IS NULL ORDER BY 123'
回顾SQL查询处理的过程,Moodle自定义了`fix_sql_params`和`emulate_bound_params`函数对替换参数进行了格式检查,但是`sortorder`并没有纳入检查范围之内,从而最终导致了注入漏洞。
diff结果如下:
新增了对`$sortorder`参数格式的检查。
由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,且听安全团队及文章作者不为此承担任何责任。
点关注,不迷路!
关注公众号回复“漏洞”获取研究环境
原文始发于微信公众号(且听安全):【最新漏洞预警】CVE-2022-0332 Moodle REST Web接口审计与H5P插件SQL注入漏洞分析