この文書は2016年以降更新されていません

REST セキュリティに関するチートシート

OWASP 作成
ジャンプ先: 移動検索
Cheatsheets-header.jpg

最終改訂日 (yy/mm/dd): 2015/12/04

はじめに

REST (REpresentational State Transfer) は、システム内のエンティティを URL パス要素によって表現するための手段です。REST は、アーキテクチャを指す言葉ではなく、Web 上のサービスを構築する際のアーキテクチャスタイルを指す言葉です。REST による Web ベースのシステムとの対話では、複雑なリクエスト本文や POST パラメーターを使わず、簡素化された URL を使用してシステム上のエンティティを指定することを可能にします。このドキュメントは、REST ベースのサービスに役立つベストプラクティスのガイドとして使用できます。

認証とセッション管理

RESTful Web サービスでは、POST によってセッショントークンを確立するか、または POST 本文の引数や Cookie として API キーを使用することによって、セッションベースの認証を使用する必要があります。ユーザー名、パスワード、セッショントークン、および API キーは URL に含まれていてはいけません。URL は Web サーバーログに取り込まれる可能性があり、これらの情報がログに記録されてしまいます。

適切:

不適切:

セッション状態の保護

Web サービスの多くは、できるだけステートレスであるように作成されます。その結果、状態を表す BLOB がトランザクションの一部としてやりとりされることになります。

  • サーバー側キャッシュでクライアントの状態を管理するには、セッショントークンまたは API キーのみを使用することを検討してください。これは、通常の Web アプリで使用されている方法とまさに同じであり、ほどほどに安全です。
  • リプレイ攻撃防止。攻撃者は BLOB を切り取って貼り付けることによって、他人になりすまします。セッショントークンまたは API キー、日時、およびIP アドレスに対して生成された、時間制限のある暗号化キーを使用することを検討してください。リプレイ攻撃対策として、認証トークンを保持するローカルクライアントストレージに対する何らかの保護を実装してください。
  • 容易に復号化できるようであってはなりません。内部の状態を変更して大幅な改善を図ります。

要するに、たとえブローシュアウェア Web サイトであっても、 https://example.com/users/2313/edit?isAdmin=false&debug=false&allowCSRPanel=false を挿入してはなりません。たちまち、多数の管理者、ヘルプデスク担当者、および "開発者" に助けを求めるはめになります。

認可

ファーミング対策

価格比較サイトや Web 集約サービスなど、多数の RESTful Web サービスの情報を集約して一か所からアクセスできるようにするサービスが作られています。このような使い方を阻止する技術的な方法はないため、高速のファーミングを有料で可能にする、あるいは契約条件に基づいてサービスを制限するなど、ビジネスモデルとして推進する手段を検討すべきです。CAPTCHA やこれに類似するその他の方法は、比較的単純な不正利用者に対処するために役立つ場合がありますが、資金面や技術面で余裕のある不正利用者には対処できません。クライアントTLS 証明書の使用は、信頼された組織へのアクセスを制限するための手段になることもありますが、これは決して確実なものではありません。特に、証明書が故意にまたは誤って外部に流出した場合、制限は確実なものとはなりません。

HTTP メソッドの保護

RESTful API では、しばしば GET (レコードの読み取り)、POST (作成)、PUT (置換 / 更新)、および DELETE (削除) が使用されます。個々のリソースコレクション、ユーザー、アクションのすべてに対して、これらのすべてが有効なわけではありません。受けとった HTTP メソッドが、セッショントークン / API キーと、関連するリソースコレクション、アクション、およびレコードに対して有効であることを確認する必要があります。たとえば、図書館用の RESTful API では、匿名ユーザーに対して、蔵書目録内の項目の DELETE 操作を許可することは適切ではありませんが、蔵書目録内の項目の GET 操作については許可しても問題ありません。それに対し、図書館員の場合は、これらのどちらの使用についても有効です。

許可対象メソッドのホワイトリストの作成

RESTful サービスでは、あるエンティティに対する様々な操作を、URL に対して複数のメソッドを許可することで実現することがよくあります。たとえば、 GET リクエストはエンティティの読み取り、 PUT は既存のエンティティの更新、 POST は新しいエンティティの作成、 DELETE は既存のエンティティの削除に使用されます。許可対象のメソッドを適切に制限することが重要です。許可対象のメソッドのみが機能し、その他のメソッドでは適切なレスポンスコード ( 403 禁止) が返されるようにします。

特に Java EE では、これを適切に実装することは難しい場合があります。このたぐいのよくある誤りについては、「Bypassing Web Authentication and Authorization with HTTP Verb Tampering」を参照してください。

特権を必要とするアクションと機密のリソースコレクションの保護

すべてのユーザーがすべての Web サービスに対する権利を保有しているわけではありません。これは非常に重要です。管理用の Web サービスが悪用されないようにする必要があるからです。

セッショントークンまたは API キーを Cookie または本文パラメーターとともに送信することによって、特権を必要とするコレクションやアクションが不正に使用されることを適切に防ぐ必要があります。

クロスサイトリクエストフォージェリに対する防御

RESTful Web サービスによって公開されるリソースに対しては、あらゆる PUT、POST、および DELETE リクエストをクロスサイトリクエストフォージェリ (CSRF) から保護することが重要です。代表的な方法として、トークンベースのアプローチがあります。CSRF 防御の実装方法の詳細については、「クロスサイトリクエストフォージェリ (CSRF) の防止策に関するチートシート」を参照してください。

XSS がアプリケーション内に存在する場合、CSRF は、ランダムトークンを使用しても、容易に実行できてしまうため、XSS の防止方法についてもよく理解してください。

セキュリティで保護されていない直接的なオブジェクト参照

言うまでもないことかもしれませんが、銀行口座の REST Web サービスについては、主キーと外部キーに対する十分なチェックが必ず実行されるようにする必要があります。

この場合、あらゆる口座から他のあらゆる口座への送金ができてしまいます。これは明らかにばかげています。これは、ランダムトークンを使用しても、安全にはなりません。

この場合、あらゆる請求書のコピーを取得できてしまいます。

この場合、本質的に、データのコンテキストによるアクセス制御を適用する必要があります。URL や、さらには POST されるフォームには、アクセス制御 "キー"、またはこれに類似する自動検証機能を提供するものが含まれていてはいけないのです。リクエストごとに、データコンテキストチェックをサーバー側で実行する必要があります。

入力値検証

入力値検証 101

入力値検証に関する知識のすべてを RESTful Web サービスに適用してください。そしてさらに 10% 上乗せしてください。なぜなら、自動ツールを使用すれば、インターフェイスに対する高速なファジングを何時間も連続して行うことが容易にできるからです。したがって、次のようになります。

  • ユーザーの支援 > 入力の拒否 > サニタイズ (フィルタリング) > 入力値検証なし

ユーザーの支援が最も有用です。なぜなら、"問題はキーボードとコンピューターの間にある" (PEBKAC) というのが最も一般的なシナリオであるためです。Web サービスへのユーザーによるデータ入力が高品質なものになるよう、ユーザーを支援します。たとえば、入力された住所に対して必ず妥当な郵便番号が入力されるようにしたり、妥当な日付が入力されるようにします。妥当でない入力は拒否します。それでも入力を続行してくる場合や、テキストフィールドなどの検証が難しいフィールドである場合は、入力のサニタイズを行います。サニタイズは強力な対策ではありませんが、XSS や SQL インジェクション攻撃に遭うよりはましです。サニタイズまたは入力値検証なしという低い対策レベルで対処せざるを得ない場合は、アプリケーションの出力エンコードをきわめて強力なものにする必要があります。

入力値検証エラーをログに記録します。作成したクライアント側コードで対象の Web サービスを呼び出すことを想定している場合は、特にその必要があります。実際には、Web サービスはあらゆる人物によって呼び出される可能性があります。そのため、入力値検証エラーを 1 秒間に何百回も発生させているユーザーはよからぬことをたくらんでいると想定すべきです。また、悪用を防止するために、レート制限によって API の 1 時間または 1 日あたりのリクエスト数を特定の数に制限することを検討します。

セキュリティで保護された解析

受信したメッセージの解析にはセキュアなパーサーを使用します。XML を使用する場合は、必ず XXE や同様の攻撃に対する脆弱性がないパーサーを使用します。

厳密な型チェック

許容される値が true または false、数値、あるいは少数の入力可能値のうちのいずれかに限定されている場合、ほとんどの攻撃は実行困難になります。早急に、受信データに対する厳密な型チェックを行ってください。

受信するデータの Content-Typeの検証

新たなデータを POST または PUT する際、クライアントはサーバに送るデータの Content-Type ( application/xml application/json など) を指定します。サーバーは、指定された Content-Type をうのみにせず、常に、Content-Type ヘッダーとコンテンツ自身が一致することを確認する必要があります。Content-Type ヘッダーがない場合や、Content-Type ヘッダーが想定外のものである場合、サーバーは 406 受信不可 レスポンスによってコンテンツを拒否しなければなりません。

レスポンスタイプの検証

一般に、REST サービスは複数のレスポンスタイプ ( application/xml application/json など) を許容し、クライアントは リクエスト内の Accept ヘッダーによってレスポンスタイプの優先順位を指定します。絶対に避けるべきなのは、 リクエスト内の Accept ヘッダーをレスポンスの Content-type ヘッダーに単純にコピーすることです。許容されるタイプのいずれも Accept ヘッダーに指定されていない場合、リクエストを拒否するようにします ( 406 受信不可 レスポンスによって 拒否する のが理想的)。

一般的なレスポンスタイプとして多数の MIME タイプがあるため、クライアントで具体的にどの MIME タイプを使用する必要があるのかを文書化しておくことが重要です。

XML 入力値検証

XML ベースのサービスは、セキュアな XML 解析を使用することによって、XML ベースの一般的な攻撃から保護する必要があります。通常、これは XML 外部エンティティ攻撃や XML 署名ラッピングなどに対する防御を意味します。このような攻撃の例については、http://ws-attacks.org を参照してください。

フレームワークが提供する検証機能

Jersey など、多数のフレームワークでは、リクエストまたはレスポンス時にフレームワークによる妥当性制約を自動的に適用させることができます(詳細については、「Bean Validation Support」を参照してください)。この場合、JSON または XML データ構造のマーシャリング解除前の検証は実行されませんが、マーシャリング解除後、データがアプリケーションに提供される前に検証が実行されます。

出力エンコード

セキュリティヘッダーの送信

所定のリソースのコンテンツがブラウザーによって正しく解釈されるように、サーバーは常に正しい値を指定した Content-Type ヘッダーを送信する必要があります。望ましくは、Content-Type ヘッダーに文字セットを含めるべきです。また、サーバーは X-Content-Type-Options: nosniff を送信して、ブラウザーが独自に Content-Type を検出しようとするのを防止する必要があります (サーバーが送ったものと異なる Content-Type を検出する場合 XSS につながる可能性があります)。

さらに、クライアントは X-Frame-Options: deny を送信して、古いブラウザーでのドラッグアンドドロップクリックジャッキング攻撃を防止する必要があります。

JSON エンコード

JSON エンコーダーでの主な問題の 1 つは、恣意的な JavaScript リモートコードのブラウザー内での実行、または node.js を使用している場合はサーバー上での実行を防止することです。適切な JSON シリアライザーを使用して、ユーザーが指定したデータを適切にエンコードし、ユーザー指定入力のブラウザーでの実行を防止することがきわめて重要です。

ブラウザー DOM に値を挿入する際には、.innerHTML の更新ではなく、 .value/.innerText/.textContent を使用することを 真剣に検討してください。 それによって、単純な DOM XSS 攻撃を防止できます。

XML エンコード

XML は文字列の連結によって構築してはいけません。常に、XML シリアライザーを使用して作成する必要があります。それによって、ブラウザーに送信される XML コンテンツが解析可能なものとなり、XML インジェクションが回避されます。詳細については、「Web サービスのセキュリティに関するチートシート」を参照してください。

暗号化

通信中のデータ

完全に読み取り専用のパブリックインフォメーションでない限り、TLS の使用を強制すべきです。特に、認証情報、更新や削除などの操作に関するトランザクションが実行される場合は、その必要があります。TLS のオーバーヘッドは、最近のハードウェアではごくわずかで、待ち時間が少し延びるぐらいであり、それを補って余りある代償としてエンド ユーザーの安全性が高まります。

高特権 Web サービスに対しては、相互認証されたクライアント側証明書を使用して、さらなる保護を適用することを検討してください。

保存中のデータ

保存されている機密データやアクセス制限されているデータの適切な処理については、あらゆる Web アプリケーションごとに主要な手法を適用することを推奨します。詳細については、「OWASP Top 10 2010 - A7 Insecure Cryptographic Storage」を参照してください。

関連資料

OWASP チートシートプロジェクトホームページ

開発者のためのチートシート (ビルダー)

評価に関するチートシート (ブレーカー)

モバイルに関するチートシート

OpSec に関するチートシート (ディフェンダー)

ドラフトチートシート

Authors and primary editors

Erlend Oftedal - erlend.oftedal@owasp.org
Andrew van der Stock - vanderaj@owasp.org

Other cheatsheets

Developer Cheat Sheets (Builder)

Assessment Cheat Sheets (Breaker)

Mobile Cheat Sheets

OpSec Cheat Sheets (Defender)

Draft Cheat Sheets