WordPressの脆弱性スキャンツールwpscanを使ってみる
相変わらずKali Linuxをいじっているので、その中のツールをまた紹介しようと思う。今回は、WordPressの脆弱性診断をおこなってくれるツールWPScanを使ってみる。
WPScanとは何か
WordPressは世界中で人気があり広く使われていることから、これを狙ったアタックが多いのも事実である。特に、既知の脆弱性がある古いバージョンのものを使っていると危ない。ということで、WordPressをHTTPスキャンすることで脆弱性診断が行えるのがこのWPScanである。
モノとしてはRubyで書かれたツールであり、特にKali Linuxでなくとも動かすことができる(最初のbundlerで色々入れないといけないのが面倒だが……)。ダウンロードして中身を覗いてみると分かるけど、data/plugin_vulns.xml などに過去の脆弱性を丁寧にリストアップしてくれており、なかなか便利そうなツールだ。
使い方
Kali Linuxにはデフォルトで入っているので、コマンドラインからwpscanと叩けば良い。引数無しで実行すると使い方のヘルプが表示される。ここでは代表的な使い方を順に見てみる。以下の例では、最新版のWordPressを使ってしまうとつまらないので、少し古い WordPress 3.3 を利用しています。
オンラインスキャン
まずはおもむろにノーマルな(?)オンラインスキャンをおこなってみる。このモードは単純に外から見える部分をアクセスして、プラグインなどに脆弱性が無いかを診断してくれる。--url オプションに、宛先URLを指定すれば良い。
root@kali:~# wpscan --url "http://10.211.55.18/wordpress/" ____________________________________________________ __ _______ _____ \ \ / / __ \ / ____| \ \ /\ / /| |__) | (___ ___ __ _ _ __ \ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \ \ /\ / | | ____) | (__| (_| | | | | \/ \/ |_| |_____/ \___|\__,_|_| |_| v2.1rNA WordPress Security Scanner by the WPScan Team Sponsored by the RandomStorm Open Source Initiative _____________________________________________________ | URL: http://10.211.55.18/wordpress/ | Started on Mon Aug 19 22:50:43 2013 [!] The WordPress 'http://10.211.55.18/wordpress/readme.html' file exists [!] Full Path Disclosure (FPD) in 'http://10.211.55.18/wordpress/wp-includes/rss-functions.php' [+] XML-RPC Interface available under http://10.211.55.18/wordpress/xmlrpc.php [+] WordPress version 3.3 identified from meta generator [!] We have identified 4 vulnerabilities from the version number : | | * Title: Reflected Cross-Site Scripting in WordPress 3.3 | * Reference: http://oldmanlab.blogspot.com/2012/01/wordpress-33-xss-vulnerability.html | | * Title: XSS vulnerability in swfupload in WordPress | * Reference: http://seclists.org/fulldisclosure/2012/Nov/51 | | * Title: XMLRPC Pingback API Internal/External Port Scanning | * Reference: https://github.com/FireFart/WordpressPingbackPortScanner | | * Title: WordPress XMLRPC pingback additional issues | * Reference: http://lab.onsec.ru/2013/01/wordpress-xmlrpc-pingback-additional.html [+] The WordPress theme in use is twentyeleven v1.3 | Name: twentyeleven v1.3 | Location: http://10.211.55.18/wordpress/wp-content/themes/twentyeleven/ | Readme: http://10.211.55.18/wordpress/wp-content/themes/twentyeleven/readme.txt [+] Enumerating plugins from passive detection ... No plugins found :( [+] Finished at Mon Aug 19 22:50:48 2013 [+] Elapsed time: 00:00:04
見ての通り、脆弱性を検知しご丁寧にその解説URL(モノによってはそのExploitコードも^^;)まで紹介してくれる。こりゃー便利だ。また、wp-includes/rss-functions.php というファイルを脆弱性として診断している。このスクリプトはデフォルトそのままだとエラーになるので、以下のようにPHPのエラーが出てDocumentRootの物理パスが漏洩してしまうようだ。
また、このスキャンの際のアクセスログを見ていると、以下のようにDB設定を行うwp-config.phpについてありがちなバックアップファイルを探してくれている。
10.211.55.20 - - [19/Aug/2013:22:50:43 +0900] "GET /wordpress/wp-config.php.save HTTP/1.1" 404 226 10.211.55.20 - - [19/Aug/2013:22:50:43 +0900] "GET /wordpress/wp-config.php.swp HTTP/1.1" 404 225 10.211.55.20 - - [19/Aug/2013:22:50:43 +0900] "GET /wordpress/wp-config.php~ HTTP/1.1" 404 222 10.211.55.20 - - [19/Aug/2013:22:50:44 +0900] "GET /wordpress/wp-config.php.swo HTTP/1.1" 404 225 10.211.55.20 - - [19/Aug/2013:22:50:44 +0900] "GET /wordpress/wp-config.php_bak HTTP/1.1" 404 225 10.211.55.20 - - [19/Aug/2013:22:50:44 +0900] "GET /wordpress/wp-config.bak HTTP/1.1" 404 221 10.211.55.20 - - [19/Aug/2013:22:50:44 +0900] "GET /wordpress/wp-config.php.bak HTTP/1.1" 404 225 10.211.55.20 - - [19/Aug/2013:22:50:44 +0900] "GET /wordpress/wp-config.save HTTP/1.1" 404 222 10.211.55.20 - - [19/Aug/2013:22:50:45 +0900] "GET /wordpress/wp-config.old HTTP/1.1" 404 221 10.211.55.20 - - [19/Aug/2013:22:50:45 +0900] "GET /wordpress/wp-config.php.old HTTP/1.1" 404 225 10.211.55.20 - - [19/Aug/2013:22:50:45 +0900] "GET /wordpress/wp-config.php.orig HTTP/1.1" 404 226 10.211.55.20 - - [19/Aug/2013:22:50:46 +0900] "GET /wordpress/wp-config.orig HTTP/1.1" 404 222 10.211.55.20 - - [19/Aug/2013:22:50:46 +0900] "GET /wordpress/wp-config.php.original HTTP/1.1" 404 230 10.211.55.20 - - [19/Aug/2013:22:50:46 +0900] "GET /wordpress/wp-config.original HTTP/1.1" 404 226 10.211.55.20 - - [19/Aug/2013:22:50:46 +0900] "GET /wordpress/wp-config.txt HTTP/1.1" 404 221
便利だなー。
ユーザ一覧表示モード
続いて、Enumerate usersモードというのを使ってみる。これはWordPressに設定しているユーザ一覧を表示してくれる。
root@kali:~# wpscan --url "http://10.211.55.18/wordpress/" --enumerate u (前半出力は同じなので省略) [+] Enumerating usernames ... [+] We found the following 3 user/s : +----+----------+----------+ | Id | Login | Name | +----+----------+----------+ | 1 | admin | admin | | 2 | guest | guest | | 3 | viewtest | viewtest | +----+----------+----------+ [+] Finished at Mon Aug 19 22:55:50 2013 [+] Elapsed time: 00:00:08
うへー、なぜログインIDが分かっちゃうんだろ!? このカギは、アクセスログを見てみると分かる。このEnumerate usersモードでアクセスした際のApacheのアクセスログは以下のようになっている。
10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=10 HTTP/1.1" 404 5810 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=8 HTTP/1.1" 404 5811 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=4 HTTP/1.1" 404 5808 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=5 HTTP/1.1" 404 5808 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=9 HTTP/1.1" 404 5811 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=3 HTTP/1.1" 200 7203 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=7 HTTP/1.1" 404 5808 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=6 HTTP/1.1" 404 5812 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=2 HTTP/1.1" 200 10428 10.211.55.20 - - [19/Aug/2013:22:55:45 +0900] "GET /wordpress/?author=1 HTTP/1.1" 200 8494
WordPressでは、ユーザのログインIDには数値のインデックスが付いている。そして "?author=1" の形でアクセスすると、そのインデックス番号のユーザが作成した記事が見られるようになっている。
このユーザごとのまとめページの「作成者」は、デフォルトではログインIDが表示されてしまう。いったんログインIDを取得すれば、あとはそこからブルートフォースアタックがやってくるという寸法である。
これを防ぐためには、ログインIDと表示される名前を別にすれば良い。表示される名前(Display Name,あるいはニックネーム)は管理画面のユーザ設定から変更可能である。
ここで設定できる「ニックネーム」を変えると、外から見える作成者の名前も変更される。ログインIDを推察されないためにも、必ず変えておいた方がいいだろう。この例では、guestというログインIDについて、ニックネームとしてguest-nicknameという値を設定している。
なお本来ならば、そもそもユーザを新規追加するときにニックネームを入れさせて欲しいのだが、何故かWordPressではそれはできない。新規ユーザ作成画面に、ニックネームを入力する項目が無いのだ。そのためまずユーザ新規作成を完了してから、改めて設定画面を開き直してニックネームを設定……としないといけない。ちょっと不親切、というか意味不明である。
と、ここまで書いておいてちゃぶ台をひっくり返すが、実はニックネームを付けていてもスキャンをすると元のIDは取れてしまう。
[+] Enumerating usernames ... [+] We found the following 3 user/s : +----+----------+----------------+ | Id | Login | Name | +----+----------+----------------+ | 1 | admin | admin | | 2 | guest | guest-nickname | | 3 | viewtest | viewtest | +----+----------+----------------+
むむむ、なぜ分かっちゃうんだろう? guestのニックネームはguest-nicknameにしたから、もう元のログインIDは出ていないはずだけど……。このカラクリは、結局よく分からなかった。
ちなみに、記事をひとつも投稿していないユーザの記事一覧ページは 200 OK で記事が無いと言われ、存在しないユーザの場合は 404 Not Found で記事が無いと言われるため、たとえ投稿がゼロでもユーザが存在するかどうかの判別は可能である。
と、なんだか中途半端ですがこれでおしまい。
追記
どこからログインIDを取得しているか分かったので追記しました。
http://d.hatena.ne.jp/ozuma/20130830/1377868474