Moodle开源教育系统远程代码执行漏洞

  • A+
所属分类:网络安全文章

前言

Moodle是一个广泛使用的开源电子学习软件,有超过1.27亿用户,允许教师和学生数字化管理课程活动和交换学习材料,通常由大学部署。本文我们将检查RIPsCodeAnalysis检测到的上一个Moodle版本中的关键漏洞的技术本质。它位于Moodle的Quiz组件中,可以通过教师角色成功地利用它来执行远程代码执行。如果你使用的是早于Moodle 3.5.0的版本,我们强烈建议立即更新到最新版本。

影响-谁能利用什么?

在使用默认配置运行的最新Moodle(早于3.5.0)课程中,必须为攻击者分配教师角色。通过另一个漏洞(如XSS)升级到此角色也是可能的。考虑到这些需求和漏洞的知识,攻击者将能够在运行Moodle的服务器的底层操作系统上执行任意命令。通过使用由Moodle计算的巧尽心思构建的数学公式,攻击者绕过了阻止执行恶意命令的内部安全机制。接下来我们将研究该漏洞的技术细节。

Quiz组件中的数学公式

Moodle允许教师设置一个包含多种类型问题的测试。其中包括计算问题,允许教师输入一个数学公式,由Moodle对随机输入变量进行动态评估。这样可以防止学生作弊,并简单地分享他们的成绩。例如,教师可以键入什么是{x}添加到{y}?的答案公式是{x}+{y}。然后Moodle将生成两个随机数,并为问答文本中的占位符{x}和{y}插入它们(例如3.9+2.1)。最后,它将通过对公式输入调用对安全性敏感的PHP函数eval()来计算答案6.0,该函数以其被恶意利用的风险而闻名,因为它允许执行任意PHP代码。

  1. question/type/calculated/questiontype.php public function substitute_variables_and_eval($str$dataset) { // substitues {x} and {y} for numbers like 1.2 with str_replace(): $formula = $this->substitute_variables($str, $dataset); if ($error = qtype_calculated_find_formula_errors($formula)) { return $error; // formula security mechanism }
  2.         $str=null; eval('$str = '.$formula.';'); // dangerous eval()-call return $str;
  3. }

为了强制只使用无害的PHP代码

Moodle的开发人员引入了一个验证器函数qtype_calculated_find_formula_errors(),该函数在危险的eval()调用之前被调用,目的是检测教师提供的公式中的非法和恶意代码。

  1. question/type/calculated/questiontype.php function qtype_calculated_find_formula_errors($formula) { // Returns false if everything is alright // otherwise it constructs an error message. // Strip away dataset names. while (preg_match('~\{[[:alpha:]][^>} <{"']*\}~', $formula, $regs)){
  2.         $formula = str_replace($regs[0], '1', $formula);
  3.     }
  4.     // Strip away empty space and lowercase it.
  5.     $formula = strtolower(str_replace(' ', ''$formula));
  6.     $safeoperatorchar = '-+/*%>:^~<?=&|!'; /* */ $operatorornumber = "[{$safeoperatorchar}.0-9eE]"; // [...] if (preg_match("~[^{$safeoperatorchar}.0-9eE]+~", $formula$regs)) { return get_string('illegalformulasyntax','qtype_calculated',$regs[0]);
  7.     } else { // Formula just might be valid. return false;
  8.     }
  9. }

开发一个绕过方法

正如在上面的源代码中所看到的,在最后一个preg_match()调用非常严格,除了公式中的-+/*%:^<?=&lx!.0-9EE之外,不允许使用任何字符。但是,在嵌套在一个临时循环中的str_replace()将递归地替换公式中的所有占位符,类似于{x}中的占位符。相应的正则表达式表明,考虑到{system(Ls)}是一个有效的占位符,占位符名称在其字符集中几乎不受限制,并且也将被$formula = str_replace($regs[0], ‘1’, $formula)中的1替换。这存在一个风险,因为在函数返回False之前,它将隐藏所有潜在的恶意字符,使其不受保护的preg_match()调用的影响,从而指示一个有效的公式。使用此技术隐藏恶意代码并将其与嵌套占位符结合,会出现可利用的漏洞。

Moodle开源教育系统远程代码执行漏洞

第一个恶意公式被验证器qtype_calculated_find_formula_errors()拒绝。如果我们将其作为占位符,并将其嵌入到花括号中(如第二个payload所示),验证器将不会检测到我们的攻击,但Moodle将简单地将我们的占位符替换为一个随机数1.2,然后才能到达eval()。但是,如果我们引入另一个占位符并将其直接嵌套到我们已有的占位符中,Moodle将只替换内部占位符,而一个危险的占位符将到达eval(),如表的第三行所示。此时,我们的payload将抛出一个PHP语法错误,这是因为eval()的输入是无效的PHP代码。因此,我们只需更正PHP语法,通过使用PHP注释从PHP解析器中排除无效部分,就可以在第4行使用最终的有效公式,该公式最终允许通过GET参数0执行代码。

CE安全网

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: