moodleRCE 独特的bypass思路

渗透技巧 2个月前 admin
104 0 0



moodleRCE 独特的bypass思路


ZAC安全

#2024#

    今年遇到了很多漏洞,但都没有太大兴趣。这两天看到moodle爆出了一个RCE,一是因为原学校用的就是这套框架,二是利用手法比较有趣,遂简单分析一手。


原链接: https://blog.redteam-pentesting.de/2024/moodle-rce/


01

漏洞复现

    官网下载moodle4.2.8版本

https://git.moodle.org/gw?p=moodle.git;a=snapshot;h=2d41ac46f45d49872db03db14ea3cfda1152c62c;sf=tgz

    访问主页安装

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    正式开始漏洞复现:

    Home->Available courses-> Add a new course 进行添加一个课程

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    将页面往下拉,找到Course format

    将topics format 改成 single activity format(在moodle框架中topics format相当于是一个主题论坛的课程,而我们复现需要用到测验题,所以需要更改课程类型)

moodleRCE 独特的bypass思路

    然后将type of activity改成quiz类型

moodleRCE 独特的bypass思路

    Save即可看到课程生成完成

moodleRCE 独特的bypass思路

    点击class1,写个Name即可,剩下的按默认格式

moodleRCE 独特的bypass思路

    Class1->Activity->Add question->Add->a new question

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    我们选择Calculated

moodleRCE 独特的bypass思路

    然后我们新建一个问题,其中的question test是我们的问题,这套系统中的{}是用来括变量的,中间的a相当于通配符

moodleRCE 独特的bypass思路

    答案设置成a ,grade是百分百 进行保存

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    这三个空写上我们想删除的课程id,第一次默认创建的课程id都是2,后续创建的课程id依次递增

moodleRCE 独特的bypass思路

    点击add

moodleRCE 独特的bypass思路

    然后就可以save了

moodleRCE 独特的bypass思路

    跳转回来,我们在点击test1,进行二次编辑

moodleRCE 独特的bypass思路

    将答案改成

((acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2) . 0+acos(2)) ^ (8 . 4 . 2 . 8 . 8 . 3 . 4 . 0 . 0 . 0 . -1 . 3) ^ (2 . 0 . 0 . 3 . 0 . 0 . 0 . 0 . 0 . -8 . 1 . 0) ^ (0 . 0 . 0 . 0 . 0 . 0 . -2 . 1 . 4 . 6 . 0 . 0) ^ (0 . 0 . 0 . 0 . -8 . 8 . 0 . 0 . 2 . 0 . -8)){a}

moodleRCE 独特的bypass思路

    然后保存,会发现有个报错,不用管,忽略即可

moodleRCE 独特的bypass思路

    回到主页,点击class1->preview quiz

moodleRCE 独特的bypass思路

moodleRCE 独特的bypass思路

    发现课程已经被删除

moodleRCE 独特的bypass思路

moodleRCE 独特的bypass思路

    而RCE的方式与上面几乎相同,用作者给的脚本跑一下payload

moodleRCE 独特的bypass思路

((acos(2) . 0+acos(2) . 0+acos(2)) ^ (2 . 1 . 1 . 0 . 0 . 0 . 0) ^ (1 . 0 . 0 . 0 . 0 . 0 . 0) ^ (0 . 0 . -4 . 8 . 8 . 1) ^ (-8 . 2 . 3 . 7 . 0 . 0)){a}

moodleRCE 独特的bypass思路

    该RCE只能使用phpinfo,DELETE_COURSE这种单参数的函数,利用受限

    进阶方式如下,question text中设置为{b}

moodleRCE 独特的bypass思路

    打入payload

(1)->{system($_GET[chr(97)])}

moodleRCE 独特的bypass思路

    保存进行下一步,f12,将所有payload变量设置为0

moodleRCE 独特的bypass思路

    点击next pages,会发现报错

Exception - system(): Argument #1 ($command) cannot be empty

moodleRCE 独特的bypass思路

    我们直接url打入命令即可成功完成RCE

moodleRCE 独特的bypass思路

    原作者给的验证脚本是substitute_variables_and_eval

moodleRCE 独特的bypass思路

    在源码中找到该函数进行跟踪分析,我们可以看到字符串过了一个substitute_variablesqtype_calculated_find_formula_errors两个部分就直接拼进eval了

moodleRCE 独特的bypass思路

    而该函数调用的位置也比较明显,在calculate函数中,而在经过这几个函数过滤后直接放进了calculate_raw中的eval函数中

moodleRCE 独特的bypass思路

   那么我们一起来分析下这些过滤语句都是什么,先进入qtype_calculated_find_formula_errors

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    一点点走,首先过滤了注释符号和php的<??>

[‘//’, ‘/*’, ‘#’, ‘<?’, ‘?>’]

moodleRCE 独特的bypass思路

    然后是将所有变量都被替换为数字1.0,这里我们可以看上面的PLACEHODLER_REGEX定义。假设公式是 “{a} + {b} * {c}”,那么正则表达式会匹配 {a}, {b} 和 {c},并将它们替换为 ‘1.0’,得到的结果是:”1.0 + 1.0 * 1.0”

moodleRCE 独特的bypass思路

moodleRCE 独特的bypass思路

    这段理解较为简单,将公式中的所有字符转为小写并移除空格,然后 设置允许的操作符,例如加减乘除等常用的数学符号

moodleRCE 独特的bypass思路

    然后进行正则表达式,判断函数格式以及参数,然后方便进行下一步的判断,比如pi这种无参数函数,如果给他参数就会报错。还有单参数或多参数的函数判断

moodleRCE 独特的bypass思路

    通过这些后进行一次正则替换,将函数调用变成1.0,例如以下示例

"3 + sin(30) * max(10, 20)"

    就会被替换成

"3 + 1.0 * 1.0"

moodleRCE 独特的bypass思路

    最后再确定是否有非法字符,然后return,这就是qtype_calculated_find_formula_errors函数的完整逻辑

moodleRCE 独特的bypass思路

    那么如何通过以上这些操作符和数字我们创建出一个函数名呢?

    这里我们需要了解一下php中的三角函数,对于acos和asin这种反函数来说未定义的值会输出double类型的NAN

moodleRCE 独特的bypass思路

    而通过php的点号连接符,我们可以将这两个变量变成一个字符串类型的NANNAN

moodleRCE 独特的bypass思路

    但是,通过刚刚验证代码的逻辑,我们可以知道在公式调用中是无法单独使用acos(2).acos(2)的,因为其中没有操作符,两个函数拼不到一起(此时的点号无法作为小数点)

     所以稍稍将这段进行一个变种

  acos(2) . 0+acos(2)

    在意思不变的情况下,此时就可以通过逻辑代码的验证

moodleRCE 独特的bypass思路

    现在我们拥有了NA这两个字符,那么如何将这个字符变成我们想要调用的函数呢?

    答案是:异或

    逻辑很简单,ab相同为0,不同为1

moodleRCE 独特的bypass思路

    好,用一段简单的代码

echo (acos(2) . 1) ^ (0 . 0 . 0) ^ (1 . 1 . 1);

    可以生成O@O,两个字母O和一个@符号

moodleRCE 独特的bypass思路

    众所周知,在计算机中每个字母和符号都会有一个ASCII码对应,而每一个ASCII码都可以转化为二进制数字。我们就是通过异或最终的二进制数字去转成任何我们想要的字符串

    比如这个案例

    N :ASCII: 78 二进制:01001110

    0 ASCII: 48 二进制:00110000

    1 ASCII: 49 二进制:00110001

    先将N和0进行异或,然后再与1进行异或。最终异或结果为01001111 对应为ASCII 79   大写字母O

moodleRCE 独特的bypass思路

    而这里要引入一个概念,我们知道正数的二进制高位一般是0,例如5的二进制是00000101,但是我们可以利用负数补码进行高位的异或,例如-5的二进制数为11111011,这样通过各种异或,我们可以制造出任何想要的字符串

    例如我们测试用的字符串phpinfo

echo(((acos(2) . 0+acos(2) . 0+acos(2)) ^ (2 . 1 . 1 . 0 . 0 . 0 . 0) ^ (1 . 0 . 0 . 0 . 0 . 0 . 0) ^ (0 . 0 . -4 . 8 . 8 . 1) ^ (-8 . 2 . 3 . 7 . 0 . 0)))

moodleRCE 独特的bypass思路

    而这时我们还需要一剂良药,也就是变量函数的特性,比如在python当中我们可以使用如下代码打印1

moodleRCE 独特的bypass思路

    但无法直接将PRINTF这串字符作为一个函数来进行调用。而PHP刚好可以,以下两种用法结果完全一样

moodleRCE 独特的bypass思路

    好了,以上前置知识了解完,我们继续回头分析qtype_calculated_find_formula_errors

    目前我们可以通过反三角函数以及编码的特性来制作出一个我们想要的字符串,但是光一个字符串phpinfo是无法进行函数调用的,我们至少还需要一个括号phpinfo()进行执行

  此时我们的解析的字符在433 return回来,紧接着进入到436行中的substitute_values_for_eval 进行解析

moodleRCE 独特的bypass思路

    我们跟进这个函数,发现将$expression 中的所有 $this->search 值替换为 $this->safevalue

    根据注释和代码我们可知

    当变量 a 被设置为 1 时,{a} 将被替换为 (1)。因此,如果我们在上面的表达式中添加 {a},对应于 ‘PRINTF’,结果将变为 ‘PRINTF'(1)

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    而最终逃出单参数限制的RCE也是利用了php的特性

https://www.php.net/manual/en/language.variables.variable.php

moodleRCE 独特的bypass思路

    而通过这种方式我们可以将危险函数作为变量传入(在moodle中花括号里包裹变量)

(1)->{system($_GET[chr(97)])}

    我们可以拿作者原脚本进行debug查看

moodleRCE 独特的bypass思路

    将formula传入验证

moodleRCE 独特的bypass思路

    由于 -> 并不是限制的非法字符,它在该验证函数中并不会被识别为问题。这里正则匹配的规则是 {[字母开头的合法占位符名称]},并没有限定开头后的其他字符除了 >, },所以顺利通过

moodleRCE 独特的bypass思路

    可以看到,因为没有匹配到指定数学函数直接进行了break,然后通过验证return false

moodleRCE 独特的bypass思路


moodleRCE 独特的bypass思路

    最后直接进入eval进行调用

moodleRCE 独特的bypass思路

    最终官方的修复也比较简单

https://git.moodle.org/gw?p=moodle.git;a=commitdiff;h=622ee0920925e719d3e0f1215d90b813afd00ca5

    将正则加了限制,只允许字母,数字,连字符,下划线和空格。箭头括号等特殊符号不在被允许。

moodleRCE 独特的bypass思路


宣传页

ZAC安全

本人微信:zacaq999 

文章内容如有任何错误或者对不上号的,可以加我微信,感谢各位大佬们的指点

安全宝典欢迎各位大佬以投稿方式免费进入!


moodleRCE 独特的bypass思路





原文始发于微信公众号(ZAC安全):moodleRCE 独特的bypass思路

版权声明:admin 发表于 2024年9月9日 上午8:20。
转载请注明:moodleRCE 独特的bypass思路 | CTF导航

相关文章