サーバセキュリティ

【実践】Webシェル攻撃の具体例と対策 ~WordPressの脆弱性とSELinuxでの防御~

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 へアクセスし、以下の手順で設定
wp-vul-s01-01
wp-vul-s01-02
wp-vul-s01-03
wp-vul-s01-04
wp-vul-s01-05
previous arrow
next arrow
wp-vul-s01-01
wp-vul-s01-02
wp-vul-s01-03
wp-vul-s01-04
wp-vul-s01-05
previous arrow
next arrow
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 ファイルを選択し、「今すぐインストール」をクリックし、さらにプラグインを有効化します。

wp-vul-s02-01
wp-vul-s02-02
wp-vul-s02-03
previous arrow
next arrow
wp-vul-s02-01
wp-vul-s02-02
wp-vul-s02-03
previous arrow
next arrow

以上でサーバ側は完成です。

攻撃クライアント構築手順

クライアント側に必要なのは python2 と requests モジュールです。インストールします。

[root@CL ~]# dnf -y install python2
[root@CL ~]# pip2 install requests

以下のサイトからコードをコピーし、vi で貼り付けて保存し、実行権を与えます。

https://github.com/w4fz5uck5/wp-file-manager-0day/blob/master/elFinder.py
[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 を知りたい方は以下をご参照下さい。

【図解/初心者向け】SELinuxとは?〜仕組みやメリット・効果の基礎入門解説〜
SELinuxとは ~概要と仕組み~ SELinux とは Secure-Enh...

コメント

タイトルとURLをコピーしました