SSTエンジニアブログ

SSTのエンジニアによるWebセキュリティの技術を中心としたエンジニアブログです。

JSON Interoperability Vulnerabilitiesの概要

目次

前提知識

マイクロサービス アーキテクチャ[1]

マイクロサービス アーキテクチャ(多くの場合、マイクロサービスと略される)は、アプリケーション開発におけるアーキテクチャ スタイルの一つです。マイクロサービスによって、大きなアプリケーションを、それぞれが独自の責任範囲を持つ独立した小さな部分に分割できます。単一のユ ーザー リクエストを処理するために、マイクロサービス ベースのアプリケーションが多数の内部マイクロサービスを呼び出して、レスポンスを作 成します。

導入

JSON Interoperability Vulnerabilitiesとは、JSONが相互運用性に影響を与えるセキュリティ上の問題を指します。

例としてマイクロサービスを挙げます。 マイクロサービス内では複数のサービスが動いており、それらは独立して開発・実装されているので互いに内部を知らない状態で、APIを通じてやり取りしています。そのやり取りに使用されるデータがJSONである場合、各サービスごとにJSONのパーサーが存在します。 JSONのパーサーには独自の癖があるものがあり、同じJSONであっても異なる解釈をする可能性があります。これによりセキュリティの問題が生じる 可能性があります。

脆弱性の概要

JSONパーサーにはRFCの中で明確に定められていない部分の解釈など、以下のような癖があります。

  • 一貫性のない重複キーの優先順位
  • キーの衝突: 文字の切り捨て
  • キーの衝突: コメント
  • 浮動小数点および整数表現
  • JSON シリアライゼーションの癖
  • 寛大な解析

以下それぞれのおおまかな説明です。

一貫性のない重複キーの優先順位

タイトルの通りで、重複したキーを持つJSONの扱いがパーサーによって異なる可能性があります。

{
  "key":1,
  "key":100
}

キーの衝突: 文字の切り捨て

一部のパーサーは、特定の文字が文字列に含まれる場合にその文字を切り捨てる。その結果キーが重複する可能性があります。 以下は、Unicodeの例です。

JSONではUnicodeのコードポイントの表現を使うことができるが、コードポイントが正しくない場合に切り捨てられる可能性があります。

{
  "key":1,
  "key\ud800":100
}

キーの衝突: コメント

引用符なしの文字列とコメント構文のサポート有無で{key1:/*, key2:*/}のようなJSONの解釈が変わります。

浮動小数点および整数表現

数値の相互運用可能な範囲について、RFCで述べられており、その範囲から外れた値の扱いがパーサーごとに異なる可能性があり、不整合につながります。

{
  "key":999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
}

JSON シリアライゼーションの癖

データ構造の実装に依存して、シリアライズに癖が生じます。

こちらで紹介されているJavaのJSON-iteratorの例では以下のような挙動をします。

//input
obj = {"test": 1, "test": 2}
//output
obj["test"] // 1
obj.toString() // {"test": 2}

寛大な解析

末尾に不当な文字列があっても正しいJSONとして解釈し、Content-Typeを無視するような環境において、末尾の不当な文字列を許すことで、HTMLの フォームからのリクエストを正しいJSONとして解釈してしまう。CSRF攻撃が可能になることがあります。

{"test": 1}=

詳細について知りたい場合はこちらをご確認ください。

脆弱性の例

続いて、JSONの解釈の癖により、起こりうる脆弱性の例です。 一貫性のない重複キーの優先順位を例に説明します。 以下のようなアプリケーションを想定します。

アプリケーションの例
- フロントサービス - リクエストをサービスA,サービスBにそのまま転送し、レスポンスの内容を使って処理をします。 - サービスA(支払いシステム) - jsonの重複している前のキーを採用します - サービスB(受注システム) - jsonの重複している後ろのキーを採用します

この状況で以下のようなリクエストがユーザーから送信されたとします。

{
    "id":1,
    "count":1,
    "count":100
}

サービスAとサービスBは重複したキーの優先度が異なるため、異なるcountとして解釈してしまい、 支払いと受注の整合性がなくなる問題が起こる可能性があります。

このようにJSONのパーサーの解釈の癖により、各サービスごとに異なる値を使って処理を行ってしまう可能性があります。

参考文献

  1. https://cloud.google.com/learn/what-is-microservices-architecture?hl=ja
  2. https://bishopfox.com/blog/json-interoperability-vulnerabilities
  3. https://tex2e.github.io/rfc-translater/html/rfc8259.html