
みなさまこんにちは!SB C&SでFortinet製品のプリセールスを担当している草野です。
近年のWebアプリケーションでは、REST APIを中心としたアーキテクチャが広く採用されています。
フロントエンドアプリケーションやモバイルアプリ、外部サービスとの連携など、現在では多くのシステムがAPIを介して通信を行っています。
一方で、APIに対する不正な入力や仕様外のリクエストが、セキュリティリスクとなるケースも増えています。
これらが適切に検証されない場合、アプリケーションの想定外の動作を引き起こしたり、セキュリティ上の脆弱性につながる可能性があります。
こうした問題に対する対策の一つが、スキーマによるリクエスト検査です。
APIの仕様をスキーマとして定義することで、仕様に沿ったリクエストのみを受け付ける仕組みを構築できます。
本記事では、FortinetのWAF製品であるFortiWebを使用し、JSONスキーマを利用したAPIリクエスト検査の動作確認を行いました。
免責

検証環境
今回の検証では、FortiWebをワンアーム構成でAPIサーバの前段に配置し、クライアントからのAPIリクエストをFortiWeb経由でAPIサーバに送信する構成としました。
構成は以下の通りです。
なお、検証クライアントはPostmanを使用し、正常なリクエストと不正なリクエストを送信することで、FortiWebの検知動作を確認します。
事前設定
APIリクエストのJSONデータを検査するため、FortiWebで以下の設定を行います。
1. JSONスキーマの登録
2. JSONプロテクションルールの作成
3. JSONプロテクションポリシーの作成
4. Webプロテクションプロファイルの設定
5. サーバポリシーの設定
これらの設定を行うことで、FortiWebはHTTPリクエスト内のJSONデータを解析し、登録されたJSONスキーマに基づいた検査が可能です。
まず「JSONスキーマ」の登録です。事前準備したスキーマファイルをアップロードします。
「JSONプロテクションルール」でアップロードしたスキーマを指定します。
またアクションを「Alert&Deny」、トリガーポリシでは「Log」を指定することで、ブロックし、ログを出力する設定とします。
「JSONプロテクションポリシー」で、作成したルールを適用したポリシーを作成します。
次に「Webプロテクションプロファイル」において、JSONプロテクションとして作成したポリシーを設定します。
最後に「サーバポリシ」で、JSONプロテクションを設定したWebプロテクションプロファイルをポリシーに適用します。
これでFortiWebの事前設定は完了となります。
検証に使用するJSON構造
今回の検証では、ユーザー情報を登録するAPIを想定し、以下のようなシンプルなJSON構造をベースにスキーマを定義しました。
{
"userId": 10,
"email": "test@example.com",
"role": "USER",
"age": 30
}
以下がアップロードしたJSONスキーマの内容となります。
このスキーマでは、主に以下の制約を定義しています。
・必須項目(required)
・データ型(type)
・許可される値(enum)
・最大値制限
・未定義プロパティの禁止
これらの制約により、API仕様に沿ったリクエストのみを受け付ける仕組みを構築しています。
検証内容
Postmanから意図的に不正なJSONデータを送信し、FortiWebがどのように検査するかを確認しました。
まずはじめに正常なPOSTリクエストを送信してみます。
特に通信がブロックされることなく、レスポンスが正常に表示されることが確認できました。
① 必須項目(required)の欠落
それでは違反リクエストを送信してみます。アップロードしたスキーマでは "required": ["userId", "email", "role"] を定義しています。
そのため、"email" がないリクエストを送信してみます。
結果として、通信がブロックされたことが確認できました。
また以下の通りログメッセージから、アップロードしたスキーマのバリデーション違反にて検知したことも確認できます。
② データ型(type)の違反
スキーマでは、"userId" は "type": "integer" として指定しています。そのため、数値ではなく、文字列 "abc" を入力することで違反となるはずです。
実行した結果が以下の画面となります。
想定通り、このケースではデータ型の違反として検知されました。
③ enum値の違反
enum(列挙型)は、いくつかの定数を選択可能なグループとして定義するデータ型となります。
"role" は "enum": ["USER", "ADMIN"] で定義しています。そのため、"role"を "SUPERUSER" という定義されていない値を入力してみます。
結果として、enum違反として検知されました。
④ 最大値の超過
次は、定義された範囲を超える値を送信するケースです。
"age" は "maximum": 90 として定義されているため、それを超える数値を入力すれば、違反となるはずです。よって、"age"を "100" として送信してみました。
結果、想定通り違反となりました。
⑤ 未定義プロパティの追加
最後にスキーマに存在しない項目を追加します。
スキーマでは "additionalProperties": false を記載しているため、未定義の項目の送信は違反となるはずです。
そこで、未定義の項目 "gender" として "MALE" の値を入力したリクエストを送信してみます。
想定通り、ブロックされました。
さらに本当にスキーマの定義によって違反と見なしているかを確認するため、 additionalProperties: false の設定を削除してみました。
結果は以下となりますが、ブロックされずに正常にレスポンスが返ってきています。
この挙動から、FortiWebがJSONスキーマの定義を参照して、リクエスト検査を行っていることが明確に確認できました。
最後に
今回の検証では、FortiWebのJSONスキーマ機能を利用することで、APIリクエストのJSONデータを検査できることを確認しました。
APIを利用するシステムでは、仕様外のリクエストや不正な入力が、アプリケーションの脆弱性につながる可能性があります。
JSONスキーマを活用することで、API仕様に準拠したデータのみを受け付ける仕組みを構築でき、APIの安全性向上が期待できます。
APIセキュリティ対策の一つとして、JSONスキーマによる入力検査は有効なアプローチといえるでしょう。
最後までお読みいただき、ありがとうございました!
※本ブログの内容は投稿時点での情報となります。今後アップデートが重なるにつれ
正確性、最新性、完全性は保証できませんのでご了承ください。
他のおすすめ記事はこちら
著者紹介
SB C&S株式会社
技術本部 技術統括部 第3技術部 2課
草野 孝

