2017年9月22日金曜日

WordPressのプラグインWelcartにオブジェクトインジェクション脆弱性

エグゼクティブサマリ

WordPress向けの国産カートプラグインであるWelcartにオブジェクトインジェクション脆弱性があることが発表された。この脆弱性により環境依存ながらリモートコード実行の可能性があるため報告する。

はじめに

Welcartは、WordPressをベースにショッピングサイトを構築する際に便利なプラグインで、国産ということもあり日本では非常に多く用いられています。そのWelcartにオブジェクトインジェクションの脆弱性があり、公表されました。
オブジェクトインジェクション脆弱性の修正
フロントにて、オブジェクトインジェクションと思われる脆弱性が認められました。
過去のすべてのバージョンが対象となります。1.9.4にアップグレードしてください。
放置しますと、サイトに任意のファイルの埋め込まれる可能性があります。
Welcart 1.9.4 をリリースしました【脆弱性の修正】より引用
修正の差分は下記となっています。外部入力(クッキー)をデシリアライズしていて、典型的なオブジェクトインジェクションですね。


Welcartのフォーラムを見ると、既に攻撃された旨の報告が上がっています。しかし、私は、Welcartの脆弱性が原因ではないのではないかと疑っています。後述するように、Welcartの脆弱性が攻撃される条件が狭いからです。

オブジェクトインジェクションとは

Welcartのパターンのオブジェクトインジェクションについては、以下の記事で説明しているので参照下さい。
PHPのunserialize関数に外部由来の値を処理させると脆弱性の原因になる
簡単に説明するとこうです。PHPのunserialize関数に外部由来の値(この場合はクッキー)を処理させると、サーバー内で任意のクラスのオブジェクトを生成することができます。オブジェクトは単なるデータですが、各クラスにはメソッドがあるため、クラス定義によっては外部から注入したオブジェクトのメソッドが実行されるケースがあります。典型的にはデストラクタです。このため、オブジェクトの値を巧妙に調整することにより、既存クラスのデストラクタ経由で、攻撃ができる場合があります。
先のブログ記事では、デストラクタからログ・ファイルを出力していて、オブジェクトのプロパティを調整することにより、ファイル名とログの値を外部から指定することにより、PHPスクリプトを書き込む形で任意コード実行まで行う例を示しています。

リモートコード実行可能なプラグインの組み合わせを探す

前述のように、オブジェクトインジェクション単体でできることは、データとしてのオブジェクトを注入することであり、オブジェクトのメソッドは対象アプリケーションに元々あるものを攻撃に使うことになります。しかも、生成されたオブジェクトから自動的に呼びされるものを使うケースが攻撃の典型的ですので、大雑把に言ってデストラクタが攻撃に使えるかどうかが問題になります。
私がWelcartおよびWordPress本体をざっと確認した範囲では、攻撃に使えそうなデストラクタは見当たりませんでした。先に、被害例が既に報告されているがWelcartの脆弱性が原因ではないのではないかという予想を述べた理由はこれが根拠です。
しかし、一般にWordPressサイトでは多くのプラグインを同時にインストールして用いるケースが多いので、Welcart以外のプラグインで攻撃に使えるものがないかを探すことにしました。WordPressサイトによると、WordPressの公式リポジトリから公開されているプラグインは52,194個あるようですが、その中の「人気のプラグイン」として公開されている1,386個をしらみつぶしに目視確認する方法で、コード実行に悪用できるプラグインを探しました。
まず、私が注目したのは、All-in-One Event Calendarというプラグインです。人気のプラグインとしては95番目で、有効インストール数は10万以上となっています。こちらの、Ai1ec_Shutdown_Controllerクラスのデストラクタは下記のようになっています。

12: class Ai1ec_Shutdown_Controller {
          // 中略
41:   public function __destruct() {
          // 中略
56:       // execute callbacks
57:       foreach ( $this->_callbacks as $callback ) {
58:           call_user_func( $callback );
59:       }
これにより、任意の関数あるいは任意クラスの任意メソッドが呼び出せますが、惜しいことに引数が渡せません。引数なしで悪いことというのは中々できないのでこれ単独では攻撃に使えませんが、デストラクタ以外の引数のないメソッドで、もっと色々なことができるものを探せば、組み合わせで悪いことができます。
以前、Joomla!の脆弱性とされた CVE-2015-8562 に対するPoCでは、この目的のために SimplePie というフィード解析等に用いるクラスのメソッドが悪用されました。そのあたりの解説は以下を御覧ください。
脆弱性は誰のせい? PHP、MySQL、Joomla! の責任やいかに
WordPressにもSimplePieは同梱されていて、当初これが使える! と思いました。以下のメソッドです。
 448: class SimplePie
 449: {
中略
1242:   public function init()
1243:   {
中略
1306:     if ($this->feed_url !== null)
1307:     {
1308:       $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1309:
1310:       // Decide whether to enable caching
1311:       if ($this->cache && $parsed_feed_url['scheme'] !== '')
1312:       {
1313:         $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location,
                               call_user_func($this->cache_name_functon, $this->feed_url), 'spc'));
1314:       }

$this->cache_name_functon に関数名、$this->feed_url に引数をセットすればいいので、楽勝じゃん…と思ったのですが、うまく行きません。デバッガで追っかけると、このクラスはWordPressの場合、デフォルトではロードされないのです。
オブジェクトインジェクションで使えるクラスは、対象アプリケーションで元々ロードされているクラスか、オートロードで自動的にロードされるクラスでなければなりません。SimplePieはこの条件に合致しないようです。
SimplePie自体はファイルとしてはあるので、サイトのカスタマイズでSimplePieを呼び出すようにしておけば攻撃に使えますが、ちょっとわざとらしい想定ですので、他の可能性を探ることにしました。
…ということで、SimplePieに代わるクラスを他のプラグインに探すことにしました。すると、ManageWP Workerというプラグインが使えそうでした。有効インストール数は50万以上です。
こちらの MWP_WordPress_HookProxy クラスの hook() メソットが使えます。
20: class MWP_WordPress_HookProxy
21: {
中略
38:     public function hook()
39:     {
40:         call_user_func_array($this->callback, $this->args);
41:     }
このクラスをオブジェクトインジェクションしたところ、元々このクラスは読み込まれていませんでしたが、オートロードでクラス定義が読み込まれました。つまり、攻撃に使えることになります。

実験

プラグインの組み合わせがレアかなと思えるものの、悪用を避けるため、具体的な攻撃コードの公表は控えます。攻撃のおおまかな流れは下記となります。
  • MWP_WordPress_HookProxyインスタンスを生成し、callbackプロパティに関数名、argsプロパティに引数配列をセットする
  • Ai1ec_Shutdown_Controllerインスタンスを生成し、_callbacksプロパティに、先のオブジェクトと文字列 "hook"からなる配列をセットする
  • Ai1ec_Shutdown_Controllerインスタンスをシリアライズ、パーセントエンコードし、クッキーにセットする
  • Welcart等のプラグインを導入したWordPressサイトを閲覧する
実験では、 pwd > /tmp/pwd というコマンドを実行し、このファイルが生成されていることで任意コード実行を確認しました。この際のMWP_WordPress_HookProxy生成は下記となります。
class MWP_WordPress_HookProxy
{
    private $callback;
    private $args;
    public function __construct() {
        $this->callback = "system";
        $this->args = array("pwd  > /tmp/pwd");
    }
}

影響

影響を受けるサイトは、Welcart 1.9.3以前を導入しているWordPressサイトですが、前述のようにこれだけでは攻撃を受ける可能性は低く、他のプラグインやカスタマイズの状況によっては、任意コード実行の可能性があります。
実験に用いたAll-in-One Event Calendar と ManageWP - Worker はあくまで例ですし、これらに脆弱性があるわけではありません。攻撃を受ける原因は、あくまで Welcart の脆弱性にあります。

対策

対策はWelcartの最新版(本稿執筆時点では 1.9.4)にアップデートすることです。

まとめ

Welcartのオブジェクトインジェクションにより任意コード実行できる可能性について説明しました。オブジェクトインジェクションに関する記事があまりない状況ですので、具体的な事例として参考にしていただければと思います。

私が調べた範囲では、現実のサイトに対する攻撃はかなり限定的であるような印象を受けましたが、短期間での荒い調査ですので、当該のWelcartをお使いのサイトは、至急にアップデートを強く推奨します。

免責

このセキュリティ情報は予告なしに改訂される場合がある。このセキュリティ情報を適用した結果について徳丸浩およびEGセキュアソリューションズ株式会社は一切の責任を負わず、利用者の利益のために、あるがままの状態で公開するものである。


【EGセキュアソリューションズ広告】

EGセキュアソリューションズ株式会社では、WordPressを用いたウェブサイトのセキュリティ強化支援サービスを提供しています。詳しくは以下を参照下さい。

WordPressサイトのセキュリティ強化支援 | EGセキュアソリューションズ株式会社

0 件のコメント:

コメントを投稿

フォロワー