JSON におけるサービス不能攻撃および安全でないオブジェクトの生成について (CVE-2013-0269)

ruby にバンドルされている JSON に関して、サービス不能攻撃 (DoS) および安全でないオブジェクトの生成を可能とする脆弱性が報告されました。 この脆弱性は CVE-2013-0269 として CVE に登録されています。 ユーザーの皆さんには ruby を更新することを強くお勧めします。

詳細

対象のシステムに JSON ドキュメントをパースさせる際に、JSON gem (ruby にバンドルされているものを含む) に対して Ruby の Symbol オブジェクトを生成させることができます。 Ruby は Symbol オブジェクトをガーベッジコレクションで回収しないので、結果としてサービス不能攻撃が成立し得ます。

同じテクニックを利用し、対象のシステムにオブジェクトを生成させ、内部のオブジェクトのように扱わせることができます。 これらの「内部のオブジェクトのように扱われる」オブジェクトは、既存のセキュリティ機構をすり抜け、たとえば Ruby on Rails に対する SQL インジェクションの踏み台などに利用することができます。

影響を受けるコードは以下のようなものです:

JSON.parse(user_input)

`user_input` 変数は以下のような JSON ドキュメントを指しています:

{"json_class":"foo"}

JSON gem は定数 "foo" を検索しようと試みます。 この検索の際に Symbol オブジェクトが生成されます。

さらに、JSON version 1.7.x においては、以下のような JSON ドキュメントを用いて任意の属性を持つオブジェクトを生成できます:

{"json_class":"JSON::GenericObject","foo":"bar"}

このドキュメントは JSON::GenericObject のインスタンスとなり、値が "bar" である属性 "foo" を持ちます。 このようなオブジェクトのインスタンス化により任意の Symbol が生成可能であり、また特定の場合にはセキュリティ上の制限を回避するために使用できます。

注意: `JSON.load` を使用する場合、この挙動は変更されません。 `JSON.load` には信頼できない入力元からのデータを決して与えるべきではありません。 もし信頼できない入力元からの JSON ドキュメントを処理する場合には、常に `JSON.parse` を使用してください。

影響を受けるバージョンの ruby を使用している全てのユーザーは、速やかに、ruby を更新するか、以下の回避策を適用して下さい。

回避策

もし ruby あるいは JSON gem を更新できない場合、以下のコード:

JSON.parse(json)

を、次のように変更してください:

JSON.parse(json, :create_additions => false)

もし `JSON.parse` 使用部分を直接変更できない場合 (例えば multi_json のように内部で `JSON.parse` を実行している gem を利用している場合など)、以下のモンキーパッチを適用して下さい:

module JSON
  class << self
    alias :old_parse :parse
    def parse(json, args = {})
      args[:create_additions] = false
      old_parse(json, args)
    end
  end
end

影響を受けるバージョン

  • ruby 1.9.3 patchlevel 392 より前の全ての ruby 1.9 系列
  • ruby 2.0.0 patchlevel 0 より前の全ての ruby 2.0 系列
  • revision 39208 より前の開発版 (trunk)

クレジット

この問題を正しく見つけ出し、Rails チームと共に解決してくれた以下の人々に多大な感謝を捧げます:

  • Thomas Hollstegge of Zweitag (www.zweitag.de)
  • Ben Murphy

更新履歴

  • 2013-02-22 21:00:00 (JST) 初版