mixiに報告した脆弱性4件のうち、1件が評価されAmazonギフト10万円分頂いたので、その詳細を書いてみます。
mixi脆弱性報告制度とは、公式サイトによると、

本制度は、株式会社ミクシィとその子会社がリリースした、ウェブアプリケーションおよびクライアントアプリケーションの脆弱性を対象とします。

とあるように、株式会社ミクシィさんとその子会社のウェブアプリケーション、クライアントアプリケーションの脆弱性を見つけて報告したら懸賞金がもらえる制度です。
(検査対象の除外条件がいくつかあるので詳しくは公式サイトを参照)

開催期間は2013/09/30 から 2014/03/31 までです。

この制度のすごいところは有名サイト「mixi」の本番環境に対し(ルールで許されてる範囲内で)自由に検査をしてよいという点だと思います。

検査に当たっての禁止事項・制限事項としてルールのページに書いてあるのは

サービスの運営に支障を与えたり、他のユーザが所有するデータにアクセスしない限りにおいて、脆弱性発見のための調査が可能です。

これだけなので、「サービスの運営に支障を与えないように留意しながら」「他のユーザのデータにアクセスしないように留意しながら」であれば、ミクシイの本番環境で検査をすることが可能です。

(そのためサーバーに負荷をかけるような検査や、「' or 1=1--」みたいなのを不用意に発行して全件更新のSQLインジェクションが実行されてしまったりするような検査は避ける必要があります。SQLインジェクション検査の危険性についてよく分からない方はこちらのページが参考になると思います:ockeghem(徳丸浩)の日記「SQLインジェクション検査の危険性」)



私が見つけて報告したのは4件で、内容は以下のようなものでした。

・モラッポのオープンリダイレクタ(前々回書いたやつ)
報告日 11月4日
対応完了日 11月14日
報酬なしの連絡 12月5日

・http://adsmixi.net のxss
報告日 10月6日
対応完了日 12月3日
報酬なしの連絡 12月24日

・mixiモール(http://mmall.jp/)のHTTPヘッダインジェクション
報告日 10月14日
対応完了日 12月5日
報酬なしの連絡 12月24日

・mixiアンケート パラメータバグ
報告日 11月25日
対応完了日 12月18日
報酬連絡 12月24日 ¥100,000

これらは全て対応済みで、もう再現できないので説明しても問題ないため、順番に解説します。


・モラッポのオープンリダイレクタ

これは前々回のブログ記事で書いたので割愛します。


・http://adsmixi.net のxss

mixi内で読み込まれているJavascriptのソースを追っていくと、location.hashの値を加工してnew Image().srcに指定している個所があったので、その箇所にjavascript:alert(1);を指定してみたところ、IE6、IE7でalertが実行されXSSが可能でした(IETesterで検証)。

攻撃成功URLはこんな感じ。

http://adsmixi.net/ad/audiencescience/cookie.html#!host=javascript:alert(1);//

ただし、ドメインがmixi.jpでないため、cookieを読み出せるにしても被害はおそらく極小で、これは望み薄だろうなあ・・・と思っていたら案の定

弊社において検討した結果、直接的な被害の発生は
軽微である、または可能性が低いと判断させていただきました。
従いまして、報酬お支払いの対象外となりますことをご了承ください。

で報酬なしでした。


mixiモールのHTTPヘッダインジェクション

mixiモールで転送アドレスになっているURLがあり、

http://mmall.jp/slink/xxxx

のアドレスにアクセスすると

Location: http://mmall.jp/xxxx

というヘッダが発行され、そのページに転送される箇所がありました。

ここで、転送前アドレスに改行コードの「%0d」を含ませてみたところ、Location:ヘッダ内で改行として出力され、任意のHTTPレスポンスヘッダを発行させることできてしまいました。

つまり、

http://mmall.jp/slink/aaa/%0dSet-Cookie:SESSIONID=AAAAABBBBB12345; Path=/

のようなアドレスにアクセスすると

Location: http://mmall.jp/aaa/
Set-Cookie:SESSIONID=AAAAABBBBB12345; Path=/

こういうHTTPレスポンスヘッダが発行され、教科書通りのHTTPヘッダインジェクション、もしくはHTTPレスポンススプリッティング攻撃が可能となっていました。

通常は、この種類の脆弱性があると、セッション固定攻撃によるセッションの乗っ取り等危険度の高い攻撃が成立してしまうものなので、これは結構大きい脆弱性を見つけたか? と思ったのですが、mixiモールの場合、カートでの購入時などに別途ログインが必要な構造になっていたため検証した限りでは大した攻撃が成立しませんでした。
(攻撃URLを踏んだ他人がカートに入れた商品が見れる程度。攻撃対象者が購入フローに遷移し、ログインするとセッションIDとは別にハッシュ値のような値がcookieに設定されてそれで攻撃側からのセッション覗き見がガードされる。必ず先に発行されるLocationヘッダのせいですぐブラウザが別の画面に遷移してしまうので、偽BODYを作ってのXSSも成功せず、案外成立する攻撃がありませんでした。
HTTPレスポンススプリッティングは、本番環境でやってキャッシュ等で実害があると危険なので検証しませんでした。)

mixiモールと全く同じプログラムを使っていると思われるDeNAショッピングにも同様の問題があったため、IPA経由でDeNAショッピングに連絡し、mixiさんからの対応完了メールより少し先に対応完了のメールが来ました。

本件も、mixiさんからの返事は

直接的な被害の発生は軽微である、または可能性が低いと判断させていただきました。

で報酬なしでした。

潜在的には何か実害があることができそうにも思えたのですが、mixiさん側の検証でも大したことはできなかったのだと思います(HTTPレスポンススプリッティングも含め)。


・mixiアンケートのパラメータバグ

これは、脆弱性と言うよりバグに近いもので、mixiアンケート内のあるURLを操作すると、アンケート完了時にランダムにもらえるクーポンが、アンケートに全く回答しない状態でもらえてしまう現象を発見したため、クーポンを不正に取得できる手順を報告したところ、この報告は評価されて100,000円のAmazonギフトをいただきました。


(画面キャプチャあんま撮ってなかったので報告時の画像を加工して掲載)

mixiアンケートで、各アンケートの最初のページが以下のようなURLになっていたのですが、

https://mr.mplace.jp/ctrl/MON1030D.do?ActuonKey=MON1030&enqueteId=XXXXXXXX


このURLのActuonKey=MON1030をActuonKey=MON1020に打ち直すと、アンケートに全く答えていないのにアンケート回答完了画面にいきなり飛びました。

https://mr.mplace.jp/ctrl/MON1030D.do?ActuonKey=MON1020&enqueteId=XXXXXXXX


これだけではアンケートに回答したことにはならないっぽいのですが、一定の確率でアンケート最終画面でクーポンが当たることがあり、何度か試していたら、アンケートに答えていないのに自分のIDにクーポンが加算されてしまいました。

正直、これはテクニカルな意味ではあまり高度なものではなく、他の3件のどれよりも簡単な内容のものだったのですが、この現象には明らかに実害があり、この手口が広まったら大きな損害になりえたという事で評価していただいたのだと思います。
(私が不正に入手したクーポンは500円の価値があるものだったので、そういうクーポンの不正入手方法が広がったり積み重なると・・・という感じで評価されたのだと思われます)


というわけで頑張って検査したかいがありました。

評価された一件は見過ごされていたバグを見つけたという感じで、高度な脆弱性検査の知識が必要、というようなのでは全然なかったので、「4件中これが評価されたか」という印象もあるのですが、まあmixiさんからすれば実害ベースでの評価になるのは当たり前で、他の脆弱性では実害があまりなく、これが一番実害があったということでしょう。
とりあえず報酬もらえた&検査楽しいので結果オーライでした。

脆弱性報告制度は来年3月末までなのでまだまだ探してみます。

良い制度を開催していただいてありがとうございます。>mixi様


追記:ちなみに、賞金を頂くに至った一件は、最初メールが不達だったようで、他の脆弱性報告時には「受領しました」連絡が数日で来たのに、この件だけ一週間ぐらい返信がなかったので、「どうなっていますか?」と確認したらメールが届いていませんと言われメールを再送して、最終的に評価に至りました。

ちゃんとした脆弱性を報告しているのに、mixiさんから受領連絡も何も全く来ないという方は、一度情報が受領されているか確認してみたほうが良いかもしれません。(あきらめていたら賞金もらえないところだった)

このところmixiの脆弱性検査とcybozu.com security challengeをやっていたのですが、それぞれで成果が一応出たので書いてみます。
まずはcybozu.com security challengeのほう。

cybozu.com security challengeというのは、サイボウズのcybozu.com上の「kintone」というサービスなどに存在する脆弱性を見つけ出すことを競うコンテストで、賞金が高額だったりしたせいか、セキュリティ界隈の方々のtwitterで話題になっていました。

コンテストの期間は11月11日11時11分から11月25日18時までと短く、エントリー制だったので、私もエントリーして開始日を待っていました。

いざコンテストが始まってみると、別件で忙しくてなかなかログインできなかったり、検査対象の「kintone」というサービスの利用方法を理解するまでにも少し時間がかかったりしました。

会社勤めをしている人間にとっては、平日はあまり検査はできないので、週末が勝負という感じだったのですが、そうすると期間内に2回しか週末がないため、結構時間がないコンテストでした。

対象のサービス「kintone」は、かなりしっかりとした作りで隙がなかなかなく、最初全然取っ掛かりが見つけられなかったのですが、一箇所だけ悪用可能かも? という現象を見つけたので、その箇所で何かできないか試していて、ソーシャルな感じの罠を仕掛けることが一応可能だったので、それを報告しました。

その後、他の攻撃可能箇所は見つけられないままタイムオーバーという感じでした。

報告した現象は、(どこまで書いていいかわからないのでぼかして書きますが)、ある手段でフィッシングっぽいことが可能だったのですが、ユーザーを誘導して操作させる必要があったりしたため、攻撃成立の可能性は高くないという判定で、脆弱性とは認められませんでした。

しかし、報告後に、報告した現象を封じる手段を追加情報として送ったところ、機能追加を検討するという連絡があり、有益な情報を提供したということで評価ポイントを1ポイント頂きました。

ルールブックによると評価ポイント1ポイントの価値は

9.2.1 報奨金の分配形式
評価ポイントを獲得した参加者は、認定時間順に「¥12,000- * 評価ポイント」の報奨金を獲得します。

とあるので、¥12,000-のようなのですが、別のルールとして

9.2.2 報奨金の対象となる評価ポイントの上限
本コンテストでは、報奨金の対象となる評価ポイントの上限を 200 といたします。
ただし、参加者はそれ以降も評価ポイントを獲得できます。

ともあるので、報奨金の対象となってるのかどうかよく分かりません。

コンテストの最中、三日間だけ送られてきた途中経過ランキングでは、脆弱性バウンティハンターとして名高い、日本人と思われるあの方がランキング一位だったりして、「やっぱすげえなあ」と思ったりしました。(※ランキング送付一度だけと書いていましたが、よく思い返したら三度でした。修正しました)

後で出た情報では

コンテストには、日本の著名なWebセキュリティー技術者の大半が参加していた
(サイボウズ 脆弱性コンテストで19件の脅威が見つかる(日本経済新聞))

とのことなので、これを脆弱性検査サービスとしてみたら300万円でものすごい豪華な検査を受けられたということになり、サイボウズさん内心ウハウハなのではないでしょうか。

(といっても、本コンテストのために本番環境とは別に検査用の環境をわざわざ作ったり、コストが結構かかったと言っていたりしたので総額は結構かかってる気配もありますが)

コンテスト中や後の運営の対応も良く、熱気があって楽しめました。
サイボウズ様、面白い試みありがとうございました。
また同じような企画があったら参加します。

(でも今回は全然歯が立たなかったに等しい結果で、自分の脆弱性検査テクのなさに失望したので、もうちょいテクを磨かないと・・・)

mixi脆弱性報告制度の成果については次回書きます。

mixi内のサービス「モラッポ」でオープンリダイレクタ脆弱性があり、脆弱性報告後、mixiとのやりとりが全部完了して問題が解決したので、何が可能だったか書いてみます。

問題があったURL:

http://id.mplace.jp/email/notice/confirm?account_key=1&signature=1&backurl=http%3A//evilsite.test.jp/evilsite.html


このURLをモラッポログイン中の会員に踏ませると、いったんモラッポログインに利用されているID管理ドメインの正規のエラー画面になり、backurl=パラメータにURLを指定することにより、表示されているダイアログの「閉じる」を押した後に遷移するURLを自由に指定することが可能でした。
(現在はこの問題は対応されています)

当該エラー画面:


オープンリダイレクタを脆弱性とするかどうかは議論が分かれることもあるようですが、モラッポのこの画面遷移の場合、正規のエラーページをいったん経由して任意の外部ページへ遷移させることが可能だったので、遷移先のURLをモラッポの画面そっくりな画面にしておけばフィッシングができてしまうのでは? と思い、借りてるレンタルサーバに簡単な偽モラッポログイン画面を作って、そのページへリダイレクトするサンプルURLを報告しました。
(報告日 11/4)

その後、11/14に

ご報告の内容について、対応が完了いたしました。
対応に漏れなどありましたら、お手数ですがお知らせください。
報酬に関しましては、追ってご連絡いたします。

というメールが来て、確認したら任意のURLに遷移できるような挙動はなくなり、問題は解決していました。

これ以前に報告している脆弱性も何件かあったのですが、そちらの対応より本件の対応が早かったので、これだけ速攻で対応されたという事は報酬がもらえるかな? と思っていたら本日(12/5)に

ご報告の内容について、弊社において検討した結果、直接的な被害の発生は
軽微である、または可能性が低いと判断させていただきました。
従いまして、報酬お支払いの対象外となりますことをご了承ください。

という連絡が来て、報酬ゼロでした。

まあ確かに、この脆弱性はテクニカルな意味では全然難しくないものなので(URL差し替えただけ)、低評価なのも分からなくはないですが、対応が入ったということは、対応しなければならない程度には問題があると思ったからで、被害が軽微または可能性が低いというならそもそも対応入れなくて良かったはずで・・・とか考えてしまいましたが、まあ先方の評価がそうなら仕方がありません。(対応されたからにはしょぼくても千円くらいはもらえるかと思った・・・)

というわけで相変わらず脆弱性検査で全く収入が得られない当ブログ作者でした。
まあ、報告してあるやつの中には、もうちょっと高度なものもあるので、それに期待しよう・・・。

T.Terada氏の日記
■[セキュリティ]マッチするはずの正規表現がマッチしない現象
http://d.hatena.ne.jp/teracc/20100410/1270885661
の現象および周辺のケースについて、サンプルコードを書いて調べてみた。

※PHP 5.3.8 windows環境で調査

//通常
$str="abcd123";
if (preg_match('/./', $str)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}
→結果:
match

//sオプションが付いていないと改行にはマッチしない
$str="\x0a";
if (preg_match('/./', $str)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}
→結果:
unmatch

//sオプションが付いていれば改行にもマッチ
$str="\x0a";
if (preg_match('/./s', $str)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}
→結果:
match

//否定の文字セットの場合、/sをつけなくても改行にマッチ
$str="\x0a";
if (preg_match('/[^a-z]/', $str)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}
→結果:
match

//PCRE のバックトラック処理の上限を超える場合にマッチしなくなる

echo "PCRE のバックトラック処理回数の上限を超える場合にマッチしなくなる\n";
echo 'pcre.backtrack_limit:'.ini_get('pcre.backtrack_limit')."\n";
$bklimit = ini_get('pcre.backtrack_limit');

echo "case 1:マッチするケース。\n";
$str='a a';
for($i=0;$i<$bklimit-5;$i++){
    $str.=' ';
}
echo "strlen:".strlen($str)."\n";
if (preg_match('/^a(.*)a/s', $str, $match)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}

echo "case 2:マッチしなくなるケース。バックトラック処理回数がここで上限を超える\n";
$str='a a';
for($i=0;$i<$bklimit-4;$i++){
    $str.=' ';
}
echo "strlen:".strlen($str)."\n";
if (preg_match('/^a(.*)a/s', $str, $match)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}

echo "case 3:(参考)文字長は同じでもバックトラック処理が発生しないケースではマッチする\n";
//この場合、a(.*)aが最長マッチで一回目でマッチしてしまうのでバックトラック処理0回(のはず)
$str='a a';
for($i=0;$i<$bklimit-4;$i++){
    $str.=' ';
}
$str.='a';
echo "strlen:".strlen($str)."\n";
if (preg_match('/^a(.*)a/s', $str, $match)) {
    echo "match\n";
} else {
    echo "unmatch\n";
}
→結果:
PCRE のバックトラック処理回数の上限を超える場合にマッチしなくなる
pcre.backtrack_limit:1000000
case 1:マッチするケース。
strlen:999998
match
case 2:マッチしなくなるケース。バックトラック処理回数がここで上限を超える
strlen:999999
unmatch
case 3:(参考)文字長は同じでもバックトラック処理が発生しないケースではマッチする
strlen:1000000
match


正規表現のバックトラック処理:
メタ文字の最長マッチ後に、他の条件にもマッチさせるために、一度取得したメタ文字の最長マッチの長さを一文字ずつ少なくしていって、他の正規表現の条件に当てはまる文字列を見つけ出す処理の事をバックトラック処理という。

a*aaaaa みたいな正規表現の場合、aaaaaaをマッチさせる際に、最初のa*が6文字マッチさせてしまい、それから最終的に1文字まで短くしていってやっと全体の正規表現がマッチする、みたいな時、バックトラック処理が5回走ってa*のマッチを5文字短くしたことになる。

このバックトラック処理に上限値があり、その上限を超えると「マッチしなかった」という結果になるため、PHPの正規表現を使った入力チェック処理の書き方によっては、チェックをすり抜ける値を指定することができてしまう場合がある、ということ。
寺田氏のブログを引用させていただくと「マッチしない場合はチェックOK」というフローは駄目で、突破される可能性がある。

(同様に、PCREの再帰処理にも再帰処理の上限数(pcre.recursion_limit)を超えるとマッチしなくなる問題があるらしいが、正規表現が難解だったので今回は省略。誰か良いサンプル教えてください)

引数として何かのURLを受け取って、そのURLにただ飛ばすという処理をセキュアに書くのは案外チェック項目が多くて大変だったのでメモ。

・引数が正しいURL形式かチェック

・オープンリダイレクタにならないように、引数として渡されたURLが飛び先として想定内のURL(自ドメイン範囲内かなど)かチェックする。

・オープンリダイレクタを使ったURL偽装に引っかかるのは善意の第三者ユーザなので、リファラが消えていないケースが多いことを考えると、補助的な対策として、リファラに何か値があったら、想定範囲内のURLかチェックし、知らないURLから飛んできてたらエラーにするというのもありかも。

・HTTPヘッダで外部から渡されたURLにリダイレクトする場合は、URLから改行コードを削除する必要がある(HTTPヘッダインジェクション対策)。

・metaタグのrefreshに指定するURLは、IE6/7だと;で区切ってURLが複数指定できてしまい、後に指定したほうのURLに飛ぶので注意。
(参考 葉っぱ日記 IE6/7のでは「;」で区切ってURLが複数指定できる問題

・Javascriptでページを遷移させる場合、Javascriptの文字リテラルに外から渡された引数を渡すのは穴が潰しにくくて危険。Javascript文字列としてのエスケープを行う必要があるが、安全な書き方がなかなか難しく、うっかりするとJavaScriptインジェクションを食らってしまう。
(var val='{$URL}'; みたいなのは危険。)
HTML特殊文字エスケープ後、HTMLフォームのhiddenインプットに値を入れて、それをJSから参照する形にすると楽。
(参考 ockeghem(徳丸浩)の日記 XSS対策:JavaScriptのエスケープ(その3)

まだあったりするかな・・

→まだたくさんあった。
オープンリダイレクト検査:Locationヘッダ編 - T.Teradaの日記

まだあったりするだろうか。

前回のXSS Challengesに続き、こちらも有名サイトHackmeに(またも今更)挑戦してみた。
Lv5までクリア。めでたくHackmeよりハッカーの称号を頂いた。
(Hackme Lv5を解いた感想は、微妙なのでノーコメント。)

結果として、正解そのものよりも、詰まっていろいろ調べた知識のほうが「おいしかった」感じがするので、Hackmeのようなサイトはネタバレなし縛りでトライしてみるのが吉だと思う。
(とは言っても今別のクラック力問題で死ぬほど詰まっていてネタバレなし縛り挫折しそうですが)


有名なXSS Challengesに(今更)挑戦してみた。
#19までの全面クリアに成功。

用意されたフォームをSubmitし、指定のalertを出せればステージクリア。
段階的に、初歩的なレベルのXSSから、だんだん高度なレベルの問題になっていく。

サイトには一部の問題はIEで、と書いてあるが、IEの特定バージョンでないとクリアできないステージがあるので、IETester等IEのバージョンを変えてテストできるソフトが必要。
プロキシソフトはFiddlerを使った。

面白く学べるので、XSSの知識を身に付けたい方はおすすめのサイトです。
良質なXSS学習サイトを作っていただいたyamagata21氏に感謝。

Powered by Blogger.
© WEB系情報セキュリティ学習メモ Suffusion theme by Sayontan Sinha. Converted by tmwwtw for LiteThemes.com.