14.5K Views
May 08, 23
スライド概要
本資料はslideshareに掲載していたスライドを移行したものです。
GraphQLのセキュリティについて社内で発表した際の資料です。
本資料は、作成者の勉強の一環として調査・検証したものになります。間違った解釈をしている場合は、ご指摘いただければ幸いです。
都内で働くセキュリティエンジニア
GraphQL入門 +診断観点 2019/09/03(社内公開) 2022/07/28(外部公開) iwama
はじめに 本資料では、以下の内容を取り扱います。 ● GraphQLの基本的な機能の説明 ● GraphQLに関するWebアプリケーション診断の検査観点
GraphQLを触ってみたい方 以下のサイトでGraphQLを試すことができます。 外部サイトのため攻撃は行わないでください。 SWAPI GraphQL Wrapper https://graphql.org/swapi-graphqlhttps://graphql. org/swapi-graphql
目次 ● ● ● ● ● ● はじめに GraphQLとは GraphQLのフォーマット GraphQLのセキュリティ 診断観点 対象数に関する注意点
GrahpQLとは
GraphQLとは データにアクセスするための問い合わせ用の言語。 DBの制限などは特にない。 様々なプログラミング言語でライブラリが提供されて いるため、言語の縛りも余程の事がない限り問題がな い。
GraphQLの注目度 ● Facebookが2012年から開発 ● サーバサイドのWebAPI技術 ● 2015年にオープンソース化
GraphQLの注目度 日本でも徐々に利用者が増えてきており、注目されつ つある。
GraphQLの特徴 ● ● ● ● 独自のクエリ言語を使用 単一のエンドポイント 強力な型システム スキーマからドキュメントを生成できる
GraphQLを使用するモチベーション 複数のHTTPリクエストを行わないと画面を描画できな い場合など GraphQLの場合、利用者が欲しいデータをクエリに記述 することで、少ない回数で取得できる。
GraphQLを使用するモチベーション 例:REST APIを使用してユーザ、投稿、 フォロワー情報を表示する画面を描画す る場合 ①ユーザ情報を取得 ②ユーザ情報に紐づく投稿情報を取得 ③ユーザ情報に紐づくフォロワー情報を 取得 参考: https://qiita.com/haoyu_ma/items/4c7a806ca1e7fe330154
GraphQLを使用するモチベーション GraphQLなら一回で一 度に取得することもで きる 参考: https://qiita.com/haoyu_ma/items/4c7a806ca1e7fe330154
GrahpQLのスキーマと型システム
GrapQLのスキーマ GraphQLを使って、APIの仕様を定義するためにはス キーマが必要になる。 スキーマには、スキーマ定義言語(SDL(Schema Definition Language))を使う。
スキーマ定義の例 SWAPI GraphQL Wrapperの場合、schema.graphqlファイ ルに定義が記載されている。 https://github.com/graphql/swapi-graphql/blob/mas ter/schema.graphql
スキーマ定義の例 人(Person)を定義する例
フィールドと型 型 スキーマを定義する際、 フィールドと型を決める必 要がある。 型には大きく分けてスカ ラー型とオブジェクト型が 存在する。 フィールド
スカラー型 デフォルトで定義されている型。以下の5つが存在する。 ● ● ● ● ● Int Float String Boolean ID
オブジェクト型 1つ以上のフィールドを含んだグ ループ。 右の例のhomeworldフィールド は、スキーマPlanetのように複数 のフィールドのグループを型にし ているため、オブジェクト型とな る。
その他の型 他にもEnum型やList型などあるが、公式のドキュメン トを参照されたい。 https://graphql.org/learn/schema/
GrahpQLのフォーマット
基本 GraphQLのエンドポイントは基本的に /graphql データの取得は query クエリタイプ。 データの変更は mutation クエリタイプ。(削除も含む) エンドポイントやクエリタイプは、変更可能だが基本 的に変わらない事が多い。
データの取得 例
HTTPリクエスト
HTTPレスポンス
フォーマット 右図はリクエスト例
QueryType データ取得ならquery 変更ならmutation
Operation name 実行したクエリに付けるタイトルの ようなもの 変更しても実行結果に影響しない
Field スキーマで定義されたフィールド
Field 右図の例だとid:cGVvcGxlOjE=に紐づ くオブジェクト型Personのidとname フィールドを取得してくる フィールドを分ける事で、複数のオ ブジェクトを取得することもできる
複数オブジェクトの取得例
同名のオブジェクトを取得する場合 フィールド名がコンフリクトを起こしエラーになる。
Aliases(エイリアス) 問い合わせのフィールドに名前を付けること。 複数のフィールドを送った際に、同じ名前だと失敗す るために使われたりする。
Aliases(エイリアス)
Fragment(フラグメント) 共通部分のフィールドを抜き出してまとめたもの。 オブジェクトが同じもの同士でしか共通化できない。
Fragment例 下の例では、オブジェクトPersonから取得したいフィールドをフラグメン トしている
Variable(バリアブル) 引数に渡す値などをバリアブルに記載して、クエリの 外に出すことできる変数のようなもの。 バリアブルはjson形式で表現される。
バリアブル(変数)
mutation(ミューテーション) データの追加、更新、削除するときのクエリタイプ。
ミューテーション SWAPIではmutationが許可 されていなかったため、リ クエスト例のみ。
GraphQLのセキュリティ
認証や実行権限 GraphQL自体に認証の仕様はない。 そのためクライアントの認証や権限は、自前で実装す るか、認証や権限も提供されたフレームワークやエコ システムを利用する必要がある。
バリデーション GraphQLは仕様上、フィールドに対して明示的に型を指 定する必要がある。 GraphQLのスキーマと型システムで説明した通り、型に は、大きく分けてスカラータイプとオブジェクトタイ プが存在する。
バリデーション デフォルトのスカラータイプ - Int: 符号付き32ビット整数 - Float: 符号付き倍精度浮動小数点値 - String:UTF-8の文字シーケンス。 - Boolean:trueまたはfalse。
バリデーション 型のチェックはGraphQLで行われるが、不正文字や文字 長のチェックなどの検証機能は提供されていないた め、自前で実装する必要がある。
クエリの深さ 実装によって循環したクエリを行える場合がある。 ネストされたクエリはDoSにつながってしまう。 そのため、循環するようなスキーマを排除するよう設 計しなければならない。 また、最大クエリ深度の設定やタイムアウトの設定な どは、自前で実装する必要がある。
イントロスペクションクエリ 利用可能なクエリ、タイプ、ディレクティブなどの情 報を要求するための特別なクエリ。 (一般公開を想定していない場合)GraphQLのクエリ情報 が漏えいし、攻撃の手がかりを与えてしまう。 不要な場合は停止しておいたほうが良い。
イントロスペクションクエリ例 非常に長いため、下の記事を参照されたい。 https://graphqlmastery.com/blog/graphql-introspection-and-introspection-queries
診断観点
GraphQLを診断する上での注意点 ● スキーマがあると検査がしやすい。 ○ 無くても検査は可能。 ● 独自のフォーマットなので、 GraphQLに対応したスキャナーが必要。 ○ Burpだといくつかプラグインが存在する
認証や権限 前述した通り、GraphQLには認証や権限に関する仕様が ない。 認証部分は、従来のWebアプリ診断と同様に確認する必 要がある。 ● セッションに関する処理 ● 認証に関する処理 ● CSRF
認証や権限 機能実行する際の承認チェック(=権限確認)は、従来の Webアプリ診断の確認に加えて、mutationクエリタイプ が正しく制限されているか確認する。 読み取りのみを想定しているケースで、mutationクエ リが実行できてしまうと不適切な承認の脆弱性につな がる。
クライアント側での攻撃 APIの一種なので、GraphQLリクエストで返されるレスポン スを直接レンダリングすることは殆どなく、JavaScriptな どにデータとして渡されて出力されるケースが多い。 そのため、XSSなどのクライアント側の攻撃を確認する場合 は、出力されるページも確認しておく必要がある。
コマンドの実行 サーバ側でバリデーションをしていない場合は、意図 しない動作を引き起こす可能性がある。 ただし、GraphQLのバックエンドは基本的にはDBなの で、SQLインジェクション以外の脆弱性が存在する可能 性は低い。
コマンドの実行 またペイロードを送る際には、引数で渡す形式で送信 したり、Variableに展開して送信したり、Fragmentに して送るなど送り方にも色々な方法がある。 送信方法を変えてレスポンスの違いがあれば深堀して みるのも良い。
情報公開 従来のWebアプリケーション検査観点に加え、イントロ スペクションクエリや実行可能なオブジェクトの確認 なども必要。 SDLから生成されるドキュメントの説明やコメントなど に不要な情報が含まれていないかの確認も必要。
イントロスペクションクエリの検査 イントロスペクションクエリが実行できるか確認す る。 ただし、サイト利用者がGraphQLの利用を想定している 場合は指摘しなくて良い可能性がある。
利用可能なオブジェクトの検査 イントロスペクションクエリが実行できる場合、利用 可能なオブジェクトが判明できる。 GraphQLの使用を想定している場合でも、アクセスを想 定していないオブジェクトまで公開している可能性も あるため確認を行う必要がある。
ロジックを狙った攻撃 まずは一般的なWebアプリ診断の観点通りに確認。 加えて、ネストしたクエリを送って処理されたり、ネ スト量を増やして処理する時間が増加していればDoSに 繋がる可能性がある。 レースコンディション/TOCTOUの可能性も併せて確認す る必要がある。
ご清聴ありがとうございました!
参考情報 https://graphql.org/learn/ https://blog.doyensec.com/2018/05/17/graphql-secu rity-overview.html https://github.com/WebAppPentestGuidelines/graphQ LGuideLine