wp-file-managerの脆弱性を突いた任意のコードの実行の概要
簡単に Web サイトを構築できる CMS として非常に有名な WordPress ですが、その脆弱性の多さでも有名です。
今回はその一例である 2020年9月1日に公表された「wp-file-manager」というWordPress のプラグインの脆弱性 (CVE 2020-25213) を使って、任意の Linux コマンド実行する webshell 攻撃を実演します。
この脆弱性は PoC (Proof of Concept: 攻撃のサンプルコード) が github 等に公開されており、簡単に攻撃が可能です。
本脆弱性の概要としては、認証無しに任意のファイルを配置できてしまうものですが、その結果、webshell として機能する PHP ファイルを作成することで、Linux 上で色々な操作が出来てしまいます。
以下イメージ図です。
それでは、インターネット公開した WordPress をアップデートしないとどういう目に遭うのか、とくとご覧ください。
検証環境で攻撃を実演
検証環境の概要
以下の構成で検証を行いました。自宅の PC 1台です。VirtualBOX で仮想マシンを 2 台作成し、CentOS8.2 (minimal) をインストールします。そして片方を WordPress サーバ (Apache + php + mariadb) とし、もう片方を攻撃用のクライアントとします。
なお、VirtualBOX のネットワークは "ブリッジ接続" とし、PC 本体からブラウザでもアクセスできるようにしておきます。
WordPress サーバ構築手順
以下の手順で構築します。
1. timezone の変更
[root@WP ~]# timedatectl set-timezone Asia/Tokyo
2. Apache, PHP, MariaDB のインストール
[root@WP ~]# dnf -y install httpd php* mariadb-server
3. 各種サービスの自動起動および起動
[root@WP ~]# systemctl enable --now httpd mariadb php-fpm
4. SELinux の Permissive 化と firewalld 設定
[root@WP ~]# setenforce 0 [root@WP ~]# firewall-cmd --permanent --remove-service={cockpit,dhcpv6-client} [root@WP ~]# firewall-cmd --permanent --add-service={http,https} [root@WP ~]# firewall-cmd --reload; firewall-cmd --list-all
5. WordPressのインストール
[root@WP ~]# cd /var/www/html [root@WP html]# curl -O https://ja.wordpress.org/latest-ja.tar.gz [root@WP html]# tar xf latest-ja.tar.gz [root@WP html]# chown -R apache: . [root@WP html]# ls -l 合計 17372 -rw-r--r--. 1 apache apache 17782444 12月 18 22:31 latest-ja.tar.gz drwxr-xr-x. 5 apache apache 4096 12月 9 14:00 wordpress
6. DB作成とDBユーザ作成
[root@WP html]# mysql MariaDB [(none)]> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8; Query OK, 1 row affected (0.000 sec) MariaDB [(none)]> GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'P@$$w0rd'; Query OK, 0 rows affected (0.000 sec) MariaDB [(none)]> exit Bye
7. ブラウザで http://192.168.0.21/wordpress へアクセスし、以下の手順で設定
8. File Manager のバージョン 6.0 をダウンロード
通常WordPressでプラグインを追加する場合はログイン後の左ペインの「プラグイン」の「新規追加」から行いますが、最新バージョンがインストールされてしまいます。
今回は検証のため古いバージョンをインストール 6.0 をインストールするため、以下からダウンロードします。
https://ja.wordpress.org/plugins/wp-file-manager/advanced/
最下部にてバージョンを 6.0 に選択し、「ダウンロード」ボタンをクリック
wp-file-manager.6.0.zip を解凍すると、wp-file-manager.6.O.zip (ゼロではなく大文字オー) が出てきます。
大文字オーのほうをインストールするのですが、このままだと「アップロードされたファイルが php.ini の upload_max_filesize ディレクティブを越えています。」というエラーが表示されます。
なのでその前に /etc/php.ini にて upload_max_filesize を 2M から 40M へ拡張し、php-fpm を再起動します。
[root@WP ~]# vi /etc/php.ini upload_max_filesize = 2M の箇所で 2M を 40M に修正 :wq
php-fpm を再起動
[root@WP ~]# systemctl restart php-fpm
こちらを左ペインの「プラグイン」⇒「新規追加」⇒中央ペインの「プラグインのアップロード」⇒「ファイルを選択」で先ほどの zip ファイルを選択し、「今すぐインストール」をクリックし、さらにプラグインを有効化します。
以上でサーバ側は完成です。
攻撃クライアント構築手順
クライアント側に必要なのは python2 と requests モジュールです。インストールします。
[root@CL ~]# dnf -y install python2 [root@CL ~]# pip2 install requests
以下のサイトからコードをコピーし、vi で貼り付けて保存し、実行権を与えます。
[root@CL ~]# vi vul.py i コード貼り付け :wq [root@CL ~]# chmod +x vul.py
攻撃コマンドと結果
クライアント側で以下のコマンドを打ちます。
[root@CL ~]# ./vul.py http://192.168.0.21/wordpress
リモートからファイルが削除されたことが分かります。
WordPress は基本的にはブラウザから index.php が呼び出され、URI に応じて index.php が他の必要な php ファイルを呼び出していきます。今回の脆弱性はブラウザから直接「connector.minimal.php」が呼び出せる状態になっていたことが原因のようです。(本来はブラウザから直接呼び出されたときは動作しないようにコーディングすべきところ)
webshell攻撃への対策としてのSELinux
webshell 攻撃は、ファイアウォールでは防げないケースがほとんどでしょう。
WAF で防げる可能性は上がりますが、おそらく今回のような脆弱性の場合は検知できないでしょう。
そんなコストを掛けるよりも、無償で使える SELinux がとても有効なのです。
SELinux では、今回の攻撃のような httpd プロセスが Linux コマンドを実行するような『プロセスの予期せぬ動き』を検知、ブロックすることが可能です。
先ほど SELinux の設定を Permissive にしましたが、この状態では攻撃の検知ができます。
例えば先ほどの攻撃で curl コマンドでインターネット通信をした場合
$ curl https://www.yahoo.co.jp
サーバ側では audit.log (ausearch コマンドで表示) は以下のように表示されます。
[root@WP ~]# ausearch -i -l -m avc
type=AVC msg=audit(2020年12月19日 00:15:36.942:327) : avc: denied { name_connect } for pid=6016 comm=curl dest=443 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=1
avc というのは access-vector-cache のことで、SELinux でのアクセス制御のキャッシュが動作したことを示しています。comm=curl となっており、curl コマンドが制御されたプロセス、tclass=tcp_socket が制御 (denied) された対象です。
Permissive では audit.log へ出力するだけで、実際の攻撃を止めることはできませんが、Enforcing にするとログだけでなく実際に http 通信自体を止めることができます。
つまり Permissive は IDS で、Enforcing は IPS のような役割をするわけです。
なので Enforcing にすればインターネットへのデータ流出を防ぐことができます。
Enforcing は敷居が高いにしても、Permissive にしておけば SELinux 起因で不具合を起こすことは (バグを除いて) ありえませんし、攻撃の検知ができます。
例えば SSH で接続し、以下コマンドで常時監視をしておけば、リアルタイムに検知が可能です。
[root@WP ~]# tail -f /var/log/audit/audit.log | ausearch -i -l -m avc
そんなわけで、SELinux は未知の脆弱性の攻撃緩和にとても有用なわけです。DMZ に配置するサーバにはぜひ、Permissive でも導入のご検討を。
もう少し詳細に SELinux を知りたい方は以下をご参照下さい。
コメント