WordPress のsecurity系plugin の Blind SQL injection 脆弱性(CVE-2015-0894) "&'<<>\ Advent Calendar 2015 (13日目)
この記事は脆弱性"&'<<>\ Advent Calendar 2015の13日目の記事です。
前日の記事は mage ctf writeup: CVE-2015-0893です。今日は連続してCVE-2015-0894です。
脆弱性内容
JVN#30832515: WordPress 用プラグイン All In One WP Security & Firewall における SQL インジェクションの脆弱性
WordPressのpluginをいろいろ見て回っていた時期に見つけたやつで、IPAに昨年末に届け出をし、今年の3月に修正版が出ました。Wordpressのpluginはsecurity系pluginにも脆弱性が、という話をTLで見たことがありまして実際に探したら見つけてしまいました。
実際のコードです。
$events_table = AIOWPSEC_TBL_EVENTS;
if (is_array($entries)) {
//Delete multiple records
$id_list = "(" . implode(",", $entries) . ")"; //Create comma separate list for DB operation
$delete_command = "DELETE FROM " . $events_table . " WHERE id IN " . $id_list;
$result = $wpdb->query($delete_command);
クエリ文字列を動的に組み立ているあたりで嫌な感じはするのですが、$entriesの中身がどこでエスケープされているのかはパッと見ではよくわかりません。仕方なく$entries
を追っていくとリクエストのクエリパラメータの値がそのまま入っていましたので、SQLiできました。
そしてもう一種。
$orderby = !empty($orderby) ? mysql_real_escape_string($orderby) : 'login_date'; $order = !empty($order) ? mysql_real_escape_string($order) : 'DESC'; $data = $wpdb->get_results("SELECT * FROM $login_activity_table ORDER BY $orderby $order LIMIT 5", ARRAY_A); //Get the last 50 records
orderbyとorderにつかう文字列をクエリパラメータから受け取っています。一見mysql_real_escape_string
でエスケープされているように見えますが、この関数はPHP5.5.0から非推奨な上に数種の特殊文字をエスケープしてくれるだけで、空白や()
などはエスケープされません。
どちらの箇所もログインして管理者画面から操作しなければ実行されません。しかし、リクエストのクエリパラメータを受け取るため、ログイン中のユーザをうまく誘導してやれば任意のSQLを実行させることができます。 実行はできても、攻撃者は直接レスポンスを受け取れませんが、Blind SQL injection、つまりsleep関数などをうまく使ってやれば時間はかかりますがDB中のデータを抜き出すことが可能でした。
/wp-admin/admin.php?page=aiowpsec&tab=tab1&orderby=IF ( (select sleep(4) FROM wp_users where user_pass like concat( char(37),char(84),char(37))), id, id)
Time-based SQL Injectionは意外に実用的だった | 徳丸浩の日記
危険性について
Blind SQL Injectionであるのでなかなか時間がかかりますが、攻撃の際に被害者に対して気づかれずにDB上の情報を盗めます。設定を変えていない場合はsaltが同じようなので、パスワードのハッシュなどを抽出した後にパスワードをオフラインアタックで推測すること理論的には可能であるように見えます。
とはいえ、特定のpluginを入れているサイトの管理者に対してピンポイントに攻撃を仕掛けることになりますので、ソーシャルハックなどを組み合わせないとなかなか難しいです。ログインパスワードを総当り攻撃する方が楽なような気もしますが、アカウントロック機構やアクセス制限をすり抜けるなどの利点はあります。
余談
修正の発表後に、同じpluginに対してまた別の報告でSQL injectionが上がっていました。
ORDER BY句の列名をエスケープするという間違った対策に起因するSQLインジェクションの例。なんでもエスケープすればよいというものではない / “WordPress All In One WP Security & Firew…” http://t.co/lUU1fqSpWk
— 徳丸 浩 (@ockeghem) April 23, 2015
しかし、さっきの脆弱性は「All In One WP Security & Firewall」というセキュリティソフトウェアの脆弱性で、脆弱性があること自体は仕方ないと思うけど、セキュリティソフトウェアを作っているのに「開発者が分かってない」ことに呆然としてしまいますね
— 徳丸 浩 (@ockeghem) April 23, 2015
あれっと思って見てみると、mysql_real_escape_string
の部分がesc_sql
に変わっていたようですが、結局十分にエスケープできていなかったようです。
plugin周りの脆弱性への対応はやはりあまり良くないのですが、最近ではWordpress 周りの脆弱性を集約するサイト(https://wpvulndb.com/)があったり、pluginのコードを静的解析して脆弱性探すサイト php-grinder もあって、以前よりもちょっと環境が整ってきているようです。(けど使わなくていいなら使いたくはない。)
www.kantei.go.jpのXSS
一年ほど前に報告。
脆弱性
典型的なDOM Based XSSで、ソーシャルへのシェアボタンで、自分自身のurl(location.hash)を見ていたために発火
参考:複数のニュースサイトで外部サイトにシェアするボタンの実装方法に問題がある件 - 金利0無利息キャッシング – キャッシングできます - subtech
報告
IPA経由で報告。
IPAからのメールのキャプチャ。
(報告のフォーマットでは、そのサイトの連絡先も一緒に書かなければいけないため、連絡窓口を探すのに時間かかった覚えが)
対応
IPAから、対象サイトに連絡が行ったその日には、ボタンがなくなっていることを確認しました。IPA経由で連絡した中で、最速の対応でした。
いくつか報告した中では、公共性の高いサイトは機能ごと削除する対応の事が多いようです。そこまで修正が困難とは思わないのですが、他と関連しないような機能であれば削除したほうが確実というのもあり難しいところです。修正したと連絡が来て、確認してみたら直ってないケースもままあるので……。
参考:ソフトウェア等の脆弱性関連情報に関する届出状況[2014年第3四半期(7月~9月)]:IPA 独立行政法人 情報処理推進機構
危険性
見た限りではwww.kantei.go.jpにはログインする場所などはなく、ECサイトなどと違ってお金が絡む画面ももちろんないようでした。
この場合、考えられる危険性としては以下の様なものが有ります。
- 細工したURLを閲覧させることで、公式発表を偽装する
- 問い合わせフォームにXSSを使って、強制投稿させる
- マルウェアなど、危険なファイルをダウンロードさせる、またはリダイレクトさせる
- 管理者画面が同一ドメイン上に存在している場合、管理者へ向けて攻撃
とはいえ、実際にどの程度XSSが攻撃に活用される可能性があるのか、どの程度危険かはよくわかりません。 go.jpは他のドメインよりも信頼度の高いドメインであるため、それを利用されると攻撃の成功確率が高まってしまうのではと、自分は考えています。
CVEなど脆弱性単体での評価方法はあるのですが、実際の運営されているサイトに沿った評価形式もほしいところです。サイトごと(ドメインごと)に事情が様々なため難しいとは思いますが。
タイムライン
はてなブログにあったセルフXSS 脆弱性"&'<<>\ Advent Calendar 2014 (19日目)
この記事は脆弱性"&'<<>\ Advent Calendar 2014の19日目の記事です。
前の記事はid:matsukawarさんのASPXのサイトのValidation機能からみるサイト攻撃ルート - matsukawarの日記です。
はてなブログの編集モードの一つに見たままモードというのが有り、そこにセルフXSSがあったので1年ほど前に報告しました。
はてなブログではyoutubeなどの別サイトの要素を読み込む場合iframeが使用されています。
そして、iframeのsrcはjavascript:
で始まるuriを書くとXSSが起こります。当時その対策として先頭がjavascript:
だったら置換する処理が書かれていたのですがそれが不十分でした。
html中に含まれる空白などはDOMが生成される際に無視されるためjava(空白)scirpt:
などが入力されるとセルフXSSとなりました。
”HTML編集”のタブで入力して、
”見たまま編集”のタブへ移動するとアラートが動作しました。
管理者画面上でのXSSでありますが、セルフXSS、つまりユーザが自分で入力する必要がある場所なので危険性としては通常のXSSよりも低いものです。
はてなブログにはリクエストパラメータにbody=
をつけることでURLの文字列を自動的に入れることもできるので、そちらも試してみたのですが途中でエスケープされるようでDom Based XSSとしては実行できないようでした。
HTML中で無視される文字列は色々パターンがある(XSS Filter Evasion Cheat Sheet - OWASP)ので、対策としては先頭をhttp://
かhttps://
に限定するのが最も簡単だと思います。
相対パスを取りたいときは、JavaScriptでリンク先URLがhttp/httpsか確認する方法 - 葉っぱ日記の記事のように一度aリンクを生成するのが良いようです。 はてなブログでは、一度適当なDOMを生成して、それにsrcを設定した後に危険であれば置換して、その後URLを取り出しているようです。
明日はにしむねあさんです。
追記:
http://t.co/PXMFO8DhTU これ自分も報告しててしばらく修正不完全で <!--> <tag> --> が通ったんだけど、今確認したら、そっちはtinymce側のアップデートで修正されてた
— mala (@bulkneets) December 24, 2014
更に追記:
malaさんの報告が去年の9月で、自分が報告したのが今年の2月だったのでduplicateだった様子。