OWASP Cheat sheet / REST Security Cheat Sheet メモ


OWASP Cheat Sheet SeriesのREST Security Cheat Sheetについて、個人用にメモする。

## HTTPS

* 安全なRESTサービスを提供するには、HTTPSプロトコルの利用が必須である。
  * パスワードやAPIキーなどクレデンシャルなどの機微情報を保護するため。

## アクセス制御

* 非公開のRESTサービスは、各APIエンドポイントでアクセス制御を実行する必要がある。
  * モノリシックなWebサービスは、ユーザー認証、承認ロジック、およびセッション管理によってこれを実装する。
  * 遅延を最小限に抑え、サービス間の結合を減らすために、アクセス制御の決定はRESTエンドポイントによってローカルで行われる必要がある。
  * ユーザー認証は、アクセストークンを発行するIDプロバイダー（IdP）に一元化する必要がある。

## JWT

* 署名またはMACのいずれかによって整合性保護されていないJWTを許可しない。

* JWTの整合性を保護するために、MACよりも署名を優先する必要がある。

  * 整合性保護にMACが使用されている場合、JWTを検証できるすべてのサービスは、同じキーを使用して新しいJWTを作成することができてしまう。

    → 同じキーを使用するすべてのサービスが相互に信頼する必要がある。

    → サービスが危険にさらされると、同じキーを共有する他のすべてのサービスも危険にさらされる。

* 証明書利用者またはトークンコンシューマーは、JWTの整合性と含まれているクレームを検証することにより、JWTを検証する。

  * 証明書利用者は、独自の構成またはハードコードされたロジックに基づいてJWTの整合性を検証する必要がある。
  * 少なくとも次の標準的なクレームを検証する必要あり。
    * iss
    * aud
    * exp
    * nbf

* 明示的なログアウトまたはアイドル状態のためにセッションが有効期限より前に終了した場合、JWTとユーザーセッションの現在の状態の間で切断が発生する可能性がある

  * 明示的なセッション終了イベントが発生した場合、関連付けられたJWTのダイジェストまたはハッシュをAPIのブロックリストに送信する必要がある。
  * これにより、トークンの有効期限が切れるまで、リクエストに対してそのJWTが無効になる。

## API Keys

APIキーの利用により、DoS攻撃の影響を減らすことができる。※サードパーティのクライアントに発行された場合、比較的簡単に侵害される。

- 保護されたエンドポイントへのすべてのリクエストにAPIキーを要求すること。
- リクエストの受信が高頻度な場合は、`429 Too Many Requests`コードを返却すること。
- クライアントが使用契約に違反している場合は、APIキーを取り消すこと。
- 機密性の高い、重要な、または価値の高いリソースを保護するために、APIキーだけに依存しないこと。

## HTTPメソッドの制限

- 利用可能なHTTPメソッドを制限する。
- 非対応HTTPメソッドを利用したリクエストはすべて拒否する。
- 呼び出し元が、リソースの収集、アクション、および記録で着信HTTPメソッドを使用することを許可されていることを確認する。

## 入力バリデーション

- 入力パラメータ/オブジェクトを信頼しない。
- 長さ/範囲/形式と型を検証する
- APIパラメーターで数値、ブール値、日付、時刻、固定データ範囲などの強力な型を使用して、暗黙的な入力検証を行う。
- 文字列入力を正規表現で制限する。
- 予期しない/違法なコンテンツを拒否する。
- 特定の言語の検証/サニテーションライブラリまたはフレームワークを利用する。
- 適切なリクエストサイズの制限を定義し、HTTPレスポンスステータス413 Request EntityTooLargeで制限を超えるリクエストを拒否する。
- 入力検証の失敗をログに記録する。毎秒何百もの失敗した入力検証を実行している人間がいないか。
- 安全なパーサーを使用する。攻撃に対して脆弱ではないパーサーを使用する。

## コンテンツタイプバリデーション

RESTリクエストまたはレスポンスの本文は、ヘッダーの目的のコンテンツタイプと一致する必要がある。

コンシューマー/プロデューサー側で誤解を引き起こし、コードインジェクション/実行につながる可能性がある。

### リクエストのコンテンツタイプを検証する

- 予期しないまたは欠落しているコンテンツタイプヘッダーを含むリクエストを拒否する
- XMLコンテンツタイプについては、適切なXMLパーサーを利用する。
- Jerseyrライブラリ（Java）などでは、コンテンツタイプを明示的に定義することにより、意図しないコンテンツタイプを誤って公開しないようにする。

### 安全な応答コンテンツタイプを送信する

- `Accept`ヘッダーの内容を`Content-type`ヘッダーに単純にコピーしない。
- `Accept`ヘッダーに許可されるタイプの1つが含まれていない場合は、リクエストを拒否する。

応答にスクリプトコード（JavaScriptなど）を含むサービスは、ヘッダーインジェクション攻撃から防御するために特に注意する必要がある。

- `application/javascript`ではなく`application/json`と一致することを確認する。

## エンドポイント管理

- インターネットを介して管理用エンドポイントを公開することは避ける。
- 管理用エンドポイントにインターネット経由でアクセスできる必要がある場合は、ユーザーが多要素などの強力な認証メカニズムを使用する必要があることを確認する。
- 可能であれば別のNICおよび制限付きサブネット上の別のHTTPポートまたはホストを介して管理エンドポイントを公開する。
- ファイアウォールルールまたはアクセス制御リストの使用により、これらのエンドポイントへのアクセスを制限する。

## エラーハンドリング

- 一般的なエラーメッセージで応答する
  - 不必要に失敗の詳細を明らかにすることは避けること。
- 技術的な詳細（コールスタックやその他の内部ヒントなど）をクライアントに渡さない。

## 監査ログ

- セキュリティ関連のイベントの前後に監査ログを書き込む。
- 攻撃を検出するために、トークン検証エラーをログに記録する。
- 事前にログデータをサニタイズして、ログインジェクション攻撃に対処する。

## セキュリティヘッダー

次のヘッダーをすべてのAPI応答に含める。

| ヘッダ                                            | 目的                                                         |
| :------------------------------------------------ | :----------------------------------------------------------- |
| `Cache-Control: no-store`                         | 機密情報がキャッシュされないようにする。                     |
| `Content-Security-Policy: frame-ancestors 'none'` | ドラッグアンドドロップ型のクリックジャッキング攻撃から保護するため。 |
| `Content-Type`                                    | レスポンスのコンテンツタイプを指定する。                     |
| `Strict-Transport-Security`                       | HTTPSを介した接続を要求し、なりすまし証明書から保護するため。 |
| `X-Content-Type-Options: nosniff`                 | ブラウザがMIMEスニッフィングを実行したり、応答をHTMLとして不適切に解釈したりするのを防ぐため。 |
| `X-Frame-Options: DENY`                           | ドラッグアンドドロップ型のクリックジャッキング攻撃から保護するため。 |

## CORS

CORSヘッダーを配信することにより、REST APIは、どのドメイン（別名オリジン）がRESTサービスへのJavaScript呼び出しを許可されているかをブラウザーに通知する。

- クロスドメインコールがサポートされていない/予期されていない場合は、CORSヘッダーを無効にする。
- クロスドメインコールの発信元を設定するときは、できるだけ具体的かつ一般的にする。

## リクエスト上の機微情報

RESTful Webサービスは、資格情報の漏洩を防ぐように注意する必要がある。

パスワード、セキュリティトークン、およびAPIキーはURLに表示しない。これは、Webサーバーのログに記録される可能性があるため。

- `POST`/`PUT`リクエストでは、機密データをリクエスト本文またはリクエストヘッダーで転送する必要がある。
- リクエストでは`GET`、機密データをHTTPヘッダーで転送する必要がある。

## レスポンスコード

REST APIを設計するときは`200`、成功または`404`エラーだけでなく、応答には、常に意味的に適切なステータスコードを使用する。

## 参考情報

* [REST Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html)