イントロ
Webアプリには脆弱性はつきものだが、Moodleにも時々重大な脆弱性が発見される。実際にこの脆弱性を利用してMoodleサイトを攻撃してみる。
あと次回では防御方法を考える。
おことわり
このメモを試す場合は必ず自分の管理しているMoodleサイトで行うこと。いろいろと大事なものを失う可能性があるよ?
CVE-2017-2641 について
概要
CVE-2017-2641はMoodle 3.2.1以前に存在するSQLインジェクション攻撃で、ユーザプリファレンス機能の脆弱性を利用している。
Moodle公式サイトにも記載があり、commit diffを確認すると*unserialize()*にユーザ入力を渡しているのが問題点だと見られる。
実証コード (PoC)
わざわざ貼らないが、ググるとPoCが見つかるので、それを使って試してみる。試したPoCではDBを更新させるためのオブジェクトを作成してserializeしたものをJSONにしてPOSTしている。
ここで攻撃に必要になるのは以下のものになる。
- 攻撃対象のMoodleサイトのユーザアカウント
- ログイン時のCookieのMoodleSessionの値
- ログイン時のMoodleのsesskeyの値
- ログインユーザのユーザID
このPoCでは実行時にユーザプリファレンス設定ページにアクセスする必要があるため、ゲストユーザでは攻撃は行えない。また、利用している*update_user_preferences()がMoodle 3.2以降にしか存在しないため、Moodle 3.1.x以前ではこのPoCは動作しないように思える。従ってMoodle 3.2(.0)および3.2.1が対象となる。
このPoCでは、”任意のテーブルの任意のフィールドを行idを指定して更新すること”が可能であることが示されており、実際にPoCではconfigテーブルのサイト管理者のIDを指定している行をSQLインジェクションで更新し、指定したユーザIDを持つユーザをサイト管理者としている。
インストール時の設定によってはテーブル名にmdl_*とかプリフィックスがついている事があるが、Moodle側で勝手に補完してくれるから分からなくても安心♪
実際に攻撃してみる
標的サイトの準備
過去の記事に従ってMoodle 3.2のサイトを構築し、ここに「サイト管理者」と「一般ユーザ」の2つのアカウントを作成する。
事前準備
PoCの実行
これらの値を利用してPoCを実行する。実行すると下記の値が正常な値の代わりに送信される。
a:2:{i:0;a:1:{i:0;O:29:"gradereport_overview_external":0:{}}i:1;O:40:"gradereport_singleview\local\ui\feedback":1:{s:5:"grade";O:11:"grade_grade":1:{s:10:"grade_item";O:10:"grade_item":6:{s:11:"calculation";s:12:"[[somestring";s:22:"calculation_normalized";b:0;s:5:"table";s:6:"config";s:2:"id";i:25;s:5:"value";i:3;s:15:"required_fields";a:2:{i:0;s:5:"value";i:1;s:2:"id";}}}}}
確認
一度ログアウトしてから再度ログインすると一般ユーザがサイト管理者になっている。(サイト管理用メニューが表示されている)
DBを確認するとサイト管理者のユーザIDが書き換えられていることが確認できる。本来は2になっている(1はゲストユーザ)。
代わりに管理ユーザでログインするとサイト管理者で無くなっていることが分かる。
その他
下記のように指定するとMoodleサイトのlongname
を書き換える事ができる。
$table = 'course';
$rowId = 1;
$column = 'fullname';
$value = 'ALL YOUR MOODLE ARE BELONG TO US!';
解説メモ
このブログのPart3まででこの脆弱性でSQLインジェクション攻撃ができる説明がされている。
しかし今回のPoCで必要な行IDが必要な問題についてPart4で検討している点が異なっている。