パスワードを忘れた? アカウント作成
11945804 story
インターネット

2ちゃんねるにXSS脆弱性が見つかる、投稿に任意の文字列を埋め込み可能に 27

ストーリー by hylom
ごたごた続き 部門より
あるAnonymous Coward 曰く、

2ちゃんねるにXSS脆弱性が見つかった模様。すでに修正済みのようだが、投稿フォームのメールアドレス欄に特定の文字列を入力することで、任意のJavaScriptコードなどを埋め込むことが可能になっていたようだ(reddit)。

2ちゃんねるは1月より、負荷対策のためCDNサービス「CloudFlare」を導入したようなのだが、それに伴う修正のためにこの脆弱性が生まれた模様。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  •  今回の 2ch の XSS については、2chのサーバが外部のサービス経由のデータをHTMLに組み入れる際に、Shift_JIS において文字として完結していない半端バイトと、HTMLタグの属性値のダブルクォート (") が結合して Shift_JIS の2バイト文字としてブラウザが扱うことにより、属性値の終了を意味するダブルクォート (") が消失してしまい、メールアドレスとして入力した不正な JavaScript コードが実行されてしまうというものです。

     5日前にもコメント [srad.jp] しましたが、詳しくは、文字コードの脆弱性はこの3年間でどの程度対策されたか? [slideshare.net] を読んでいただけると、原因と対策が分かりやすいです。

     マルチバイトXSSに関しては、プラットフォーム側での対策は進んでいますが、ユーザー(解説本の著者を含む)の理解が不十分です。大きな書店でWebプログラミング言語の解説本を読むと、並んでいる大半の書籍にXSS対策の解説ページにおいて、マルチバイトXSSの脆弱性のあるコードが掲載されている のが現状です。

     例えば、半端な先行バイトによるXSSの対策がされている PHP の 5.3.1 より新しいバージョンであっても、単に htmlspecialchars 関数を使っただけでは、文字コード UFT-8 として処理されてしまいますから(default_charset の指定がある場合を除く)、Shift_JIS などの文字コードを使っている場合には脆弱性となるのです。

    // 【PHP における脆弱性のあるコード】 … 大半の解説書籍においてこのような脆弱性のあるコードが掲載されています
    echo '<a href="mailto:' . htmlspecialchars($_POST['email'], ENT_QUOTES) . '">メール</a>';
    ]

     正しくは、オプションの引数として、入力値の文字コードを指定する必要があります。また、その場合であっても、入力値に当該文字コードにおいて不正なデータが含まれていたり、文字として完成していない半端データが含まれていることは、あらゆる不具合や場合によっては脆弱性の原因となります。従って、ユーザーから入力されたデータ(もしくは外部サービスなどから渡されたデータ)は、全て文字エンコーディングの validation をするべきです。

    以下は、望ましいコードです。

    // 【適切なコード】

    // 下記のように、不正な文字エンコードのチェックと、文字コードを指定した上でのエスケープ処理の両方をやるべきです。

    // 文字として不正な部分のみを削除するような処理は、一般に望ましくないのでエラーにすべきです(削除した結果、問題のあるデータが生成されるケースもあることから、そのような脆弱性を生むようなコードの書き方はしない方が無難です)。
    // 従って、半端バイトなどのデータが少しでも含まれていたら、その部分だけ削除するのではなく、そのままエラーとして処理します。
    if ( !mb_check_encoding($_POST['email'], 'Shift_JIS') ) {
      die('文字エンコーディングが不正です。');
    }

    // 上記のエラーチェックの他に、エスケープ処理も行います。
    // PHP 5.5 より新しい場合 default_charset で文字コードを指定することもできます
    echo '<a href="mailto:' . htmlspecialchars($_POST['email'], ENT_QUOTES, 'Shift_JIS') . '">メール</a>';

     上記のコードにおける、入力時点での不正なエンコーディングのチェック、出力時点でのエスケープ処理のいずれかをやっていれば、外部サービス・外部データベース・外部APIなどを使わない限り、マルチバイトXSSは完全に防げますが、ユーザーからの入力を受け付ける段階での文字エンコーディングの validation と、HTML 出力段階でのエスケープ処理の、両方をやっておくことをお勧めします。前者はやらないと、文字として完結していない不正なデータが、データベース内のデータの破損やエラー発生などの不具合の原因にもなりますし、後者に関しては、外部のサービスなりAPIなりデータベースを経由した際に不正・破損データが含まれた場合の対策ともなります。

    • 残念ながら、この問題はSJISから来るものではありません。
      バックスラッシュ単体でも問題が起こることを確認しているので、エスケープ文字から来るもののようです。
      CloudFlareのemail protectionのバグなので、影響を受けるサイトは多いかもしれません。

      もうすこし詳しく書くと、
      <a href="mailto:\"></a>[...]<a href="mailto:a onmouseover=[...]//"></a>

      <a href="/cdn-cgi/l/email-protection#[...].39 [...]&lt;a href="mailto:a onmouseover=[...]//"></a>
      となってしまいます。

      CloudFlare側には既に通告済みですが、今のところ連絡ありません。
      親コメント
    • by Anonymous Coward

      // 従って、半端バイトなどのデータが少しでも含まれていたら、その部分だけ削除するのではなく、そのままエラーとして処理します。
      金絡むトコほどエラーにしないでなんとか取り込めという方向で仕様が出来てますねぇ。。
      あくまで実体験なので、二桁程度のシステム。

    • by Anonymous Coward

      そういうバグが原因だとしたら、埋め込んだ文字列からスクリプトを介するとかしないと「投稿に任意の文字列を埋め込み」は不可能ですね。
      好き放題やられる状況だったという結論は変わりませんけど。

      • 確かに、JavaScript コードで使える文字種が制限されますので(ダブルクォートや半角スペースが使えない)、「任意のJavaScriptコード」ではなく「一部文字種が制限されたJavaScriptコード」ですね。

        2ちゃんねるは、メールアドレス欄に入れた文字列が、a要素のhref属性の中に入る仕組みになっています。

        普通は、こんな感じになります。

        <a href="mailto:sage">名無しさん@アレゲいっぱい</a>

        マルチバイトXSSの脆弱性がある場合、1回メールアドレスに「【マルチバイト文字の1バイト目 (0x82)】」だけいれて書き込みをした後、 メールアドレス欄に「 onload=alert(document.title)」といれてもう一度書き込めば、JavaScript コードが実行されるはずです。

        レス2
        <a href="mailto:【マルチバイト文字の1バイト目 (0x82)】">名無しさん</a>

        レス3
        <a href="mailto: onload=alert(document.title)">名無しさん</a>

        これが、下記のように 斜体 の部分が属性値としてブラウザに認識されます。

        レス2
        <a href="mailto:【マルチバイト文字の1バイト目 (0x82) と ダブルクォートで1つの文字と認識】>名無しさん</a>

        レス3
        <a href=
        "mailto: onload=alert(document.title)">名無しさん

        分かりにくいですが、最初のa要素のhref属性を閉じるダブルクォートが消失したために、下記4行がhref属性の内容と扱われている状態です。

        mailto:【マルチバイト文字の1バイト目 (0x82) と ダブルクォートで1つの文字と認識】>名無しさん</a>

        レス3
        <a href=

        また、その次の「mailto:」の部分は、属性値が省略された属性名として扱われて、存在しない属性名なのでエラーとしてブラウザはスルーされます。

        そして、ユーザーが2回目にメールアドレスとして入力した「 onload=alert(document.title)」(最初に半角スペース有り)の、「onload」が属性名、「alert(document.title)」が属性値として扱われて、JavaScript が実行される訳です。属性値をダブルクォートで囲わない場合、半角スペースが次に入るまでは属性値と主要ブラウザはそのまま処理するからです。

        親コメント
        • by Anonymous Coward

          全ての文字列の最後に半角スペースを入れておけば解決ですよ。
          ※P言語は文字コードの探査が可能だから、定型文書くならそっちだろぅに・・・

    • by Anonymous Coward

      この問題、あるMMORPGでもあったなチャットで相手を落とせる、もちろん自分もメッセージ表示されるから自分も落ちるw
      叫べば・・・みんないなくなる。

      不正なデータを弾く条件を考えるより、正常に受け付けるデータの条件を考えた方が、条件もれがあっても大丈夫w

      • by Anonymous Coward

        ああ、あったあった。
        放置露店一掃はソレか。

  • 原因 (スコア:3, 参考になる)

    by Anonymous Coward on 2015年03月03日 12時33分 (#2770805)

    タレコミのリンクから抜粋しただけなので真偽は不明ですが。

    今回やらかしたっぽいのは2chが負荷を分散させるために噛ませた海外のCloudFlareサービスみたいで、
    それに2ch上のメールアドレスをクローラー(自動収集bot)とかで取り難いようにするために難読化する機能が
    ついてたんだけどその処理内でポカった(らしい)

    2ch.netはShift JISのページですが、Shift JISのページにCloudFlareの上記の機能を使うと脆弱性ができるとのこと。

    もう直っているらしいし、特に被害もなかったようなのでたいした話ではないですね。

    • by Anonymous Coward

      >もう直っているらしいし、特に被害もなかったようなのでたいした話ではないですね。

      別に誰もたいした話だなんて言ってないですけどね。

  • もう一個 (スコア:2, 参考になる)

    by Anonymous Coward on 2015年03月03日 12時10分 (#2770789)

    新API移行と一緒に始まる有料会員サービスの課金サイトにPOODLE [srad.jp]があったようです。

    • by Anonymous Coward on 2015年03月03日 12時27分 (#2770799)
      親コメント
      • by Anonymous Coward

        POODLE(SSL3.0)どころかSSL2.0まで有効にしたまま放置っていったいどういうことなの。

        • by Anonymous Coward

          payment.premium2ch.net = 202.218.228.235

          202.218.228.128 - 202.218.228.255
          curioworks inc.

          同社の汎用決済サービスも同様
          https://www.ssllabs.com/ssltest/analyze.html?d=paylynx.net [ssllabs.com]

        • by Anonymous Coward

                       /)
                     ///)
                    /,.=゙''"/
             /     i f ,.r='"-‐'つ____     こまけぇこたぁいいんだよ!!
            /      /   _,.-‐'~/⌒  ⌒\
              /   ,i   ,二ニ⊃( >). (<)\
             /    ノ    il゙フ::::::⌒(__人__)⌒::::: \
                ,イ「ト、  ,!,!|     |r┬-|     |
               / iトヾヽ_/ィ"\      `ー'´     /

          # よかねぇよ

    • by Anonymous Coward

      ftpとsshも開いてるよ! おまけに公開鍵認証じゃないよ!

      • by Anonymous Coward

        ftpとsshも開いてるよ! おまけに公開鍵認証じゃないよ!

        レンタルサーバー

  • by iwakuralain (33086) on 2015年03月03日 13時38分 (#2770854)

    Shift_JISってところに驚いた。
    最近はもっぱらUTF-8でウェブサイト作ったりバリデーションしてて特に問題なくいけてたので。

    # もちろんShift_JISサイトはたくさんあるのは知ってはいるんだが・・・

    • by Anonymous Coward on 2015年03月03日 15時11分 (#2770904)

      作られたのが最近じゃないからなあ

      ハングル板あたりはUTF-8だったはずだけど

      親コメント
    • by Anonymous Coward

      ログファイル(datファイル)がShift_JISのようです。

      • by Anonymous Coward on 2015年03月03日 15時26分 (#2770919)

        あれっ、意外と知られてないんですね>datがShift_JIS(てゆかWinでのAA表示意識してるからcp932か)
        UTF-8化してほしいものですが、保存時の容量とか転送量云々という理由で消極的だろうなぁ…

        ちなみに1000到達したスレのデータで元のShift_JISデータとUTF-8に変換したものをgzip圧縮で比べてみたら、
        dat・HTMLいずれもUTF-8の方が6~7KBが大きかったです。
        2ch閉鎖騒動の頃だったら十分却下の理由になりそうで辛い。

        # せめてdat出力時、Content-Typeにcharset属性付加されてないのはなんとかしてほしいAC

        親コメント
  • by Anonymous Coward on 2015年03月03日 13時11分 (#2770828)

    2chといえば新APIに対応して広告画像などからトラッキングしちゃうよーという新仕様以外は利用出来なくなるという話がありましたが
    今のところ閲覧や書き込みは出来ているようですね。

    時差があるだけなのか釣られて対応アプリに乗り換えた人間から情報収集して新たな収益にしますという事なんだろうか。

    • by Anonymous Coward

      今のところはdatアクセスが廃止されていないので、従来の専用ブラウザで読み書きできています。
      まあ、すぐに廃止したら住人が激減すると分かってるからだろうけど。
      PC用の専用ブラウザだと正式リリースでAPI対応してるのが無いですから。

typodupeerror

最初のバージョンは常に打ち捨てられる。

読み込み中...