Slide 1

Slide 1 text

Security․Tokyo #2 攻撃者の視点から見た GraphQLのセキュリティ kuzushiki 1 / 23

Slide 2

Slide 2 text

Security․Tokyo #2 自己紹介 kuzushiki とあるセキュリティベンダの診断員 (4年目) Webアプリの脆弱性診断、たまにペネトレ 最近バグバウンティにハマる 情報処理安全確保支援士 / OSCP / OSWE 2 / 23

Slide 3

Slide 3 text

Security․Tokyo #2 GraphQLって? 3 / 23

Slide 4

Slide 4 text

Security․Tokyo #2 GraphQLとは Facebookが開発した、APIのためのクエリ 言語 開発者フレンドリー 必要なデータだけを指定して取得可能 データの型を定義できる https://engineering.mercari.com/blog/entry/20220303- concerns-with-using-graphql/ より引用 4 / 23

Slide 5

Slide 5 text

Security․Tokyo #2 GraphQLのやりとりをみてみよう GraphQLクエリ レスポンス 1 query { 2 users(id: 1) { 3 id 4 username 5 } 6 } 1 { 2 "data": { 3 "users": [ 4 { 5 "id": "1", 6 "username": "admin" 7 } 8 ] 9 } 10 } 5 / 23

Slide 6

Slide 6 text

Security․Tokyo #2 GraphQLの機能とその悪用方法 6 / 23

Slide 7

Slide 7 text

Security․Tokyo #2 Introspection クライアントにAPI がどのような操作を許可しているかを伝える機能 GraphQLクライアントでのドキュメント表示やフィールド名の自動補完に用いられる 1 query { 2 __schema { 3 types { 4 fields { 5 name 6 } 7 } 8 } 9 } 1 { 2 "data": { 3 "__schema": { 4 "types": [ 5 { 6 "fields": [ 7 { 8 "name": "pastes" 9 }, 10 { 11 "name": "paste" 12 }, 13 ... 7 / 23

Slide 8

Slide 8 text

Security․Tokyo #2 Introspectionを用いた情報収集 攻撃者にもAPI がどのような操作を許可しているかが伝わってしまう… 管理用の操作を実行される恐れ 1 { 2 "data": { 3 "__schema": { 4 "types": [ 5 { 6 "fields": [ 7 ... 8 { 9 "name": "systemUpdate" 10 }, 11 { 12 "name": "systemDebug" 13 }, 14 ... 8 / 23

Slide 9

Slide 9 text

Security․Tokyo #2 Introspectionを用いた情報収集の対策 API の仕様を公開したくない場合は、Introspectionを無効にしておこう Introspectionが無効化できないサービスでは、"__schema"をWAFでブロックしよう AWS AppSyncでの対策例: https://stackoverflow.com/questions/59503969/how-to-disable- introspection-queries-with-aws-appsync-graphql 9 / 23

Slide 10

Slide 10 text

Security․Tokyo #2 Alias 名前の衝突を避け、同じフィールド名を複数問い合わせられる機能 Aliasなしだと以下のエラーとなる Fields "users" conflict because they have differing arguments. ` ` 1 query { 2 user1: users(id: 1) { 3 username 4 } 5 user2: users(id: 2) { 6 username 7 } 8 } 1 { 2 "data": { 3 "user1": [ 4 { 5 "username": "admin" 6 } 7 ], 8 "user2": [ 9 { 10 "username": "operator" 11 } 12 ... 10 / 23

Slide 11

Slide 11 text

Security․Tokyo #2 Aliasを用いた認証回避・DoS 攻撃者は1度のクエリで同一フィールドを複数要求可能に… 総当りやパスワードリスト攻撃による認証の突破 重いフィールドを何度も要求することによるDoS 1 query { 2 admin: login(user: "admin", pass: "admin") { 3 success 4 } 5 test: login(user: "admin", pass: "test") { 6 success 7 } 8 ... 9 } 1 { 2 "data": { 3 ... 4 "truepassword": [ 5 { 6 "success": true 7 } 8 ] 9 ... 10 } 11 } 11 / 23

Slide 12

Slide 12 text

Security․Tokyo #2 Aliasを用いた認証回避・DoSの対策 1度に使えるAlias数に制限を設ける コスト制限を設ける クエリの複雑さをコストとして数値化し、しきい値を超えたらエラーを返す コスト算出方法はライブラリによってまちまち ※APIの回数制限では不十分なので注意! 12 / 23

Slide 13

Slide 13 text

Security․Tokyo #2 Fragment クエリ内で繰り返し使用する部分を定義し、使い回せる機能 1 query { 2 user1: users(id: 1) { 3 ...userInfo 4 } 5 user2: users(id: 2) { 6 ...userInfo 7 } 8 } 9 10 fragment userInfo on User { 11 username 12 email 13 } 13 / 23

Slide 14

Slide 14 text

Security․Tokyo #2 Fragmentを用いたDoS Fragmentの中でもFragmentが使えることがある!? 定義のしかたによっては無限ループに陥ることに… (Circular fragments) 1 query { 2 users(id: 1) { 3 ...A 4 } 5 } 6 7 fragment A on User { 8 username 9 ...B 10 } 11 12 fragment B on User { 13 ...A 14 } 14 / 23

Slide 15

Slide 15 text

Security․Tokyo #2 Fragmentを用いたDoSの対策 すでにほとんどのGraphQLサーバでは対策済み GraphQLの仕様でfragmentはサイクルを形成してはいけないと明記されており、仕様通りに実 装できていれば問題ない RubyのHTTPサーバAgooにこの問題が存在し、脆弱性として報告された (v2.14.3で修正済み) https://nvd.nist.gov/vuln/detail/CVE-2022-30288 ” The graph of fragment spreads must not form any cycles including spreading itself. Otherwise an operation could infinitely spread or infinitely execute on cycles in the underlying data. https://spec.graphql.org/October2021/#sec-Fragment-spreads-must-not-form-cycles 15 / 23

Slide 16

Slide 16 text

Security․Tokyo #2 Field Suggestion フィールド名が間違っている場合に、正しいフィールド名を提案してくれる機能 非常に便利な機能だが… 1 query { 2 products(id: 1) { 3 name 4 price 5 } 6 } Cannot query field "products" on type "Query". Did you mean "product"? 16 / 23

Slide 17

Slide 17 text

Security․Tokyo #2 Field Suggestionを用いた情報収集 それっぽいフィールド名を大量に送り、有効なフィールド名を列挙 (Blind Introspection) clairvoyance というツールを使うと、Introspection Queryの応答に近い情報が得られる 1 query { 2 articles 3 documents 4 posts 5 ... 6 } 1 { 2 "errors": [ 3 ... 4 { 5 "message": "Cannot query field \"posts\" on type \"Query\". Did you mean \"pastes\" or \" 6 ... 17 / 23

Slide 18

Slide 18 text

Security․Tokyo #2 Field Suggestionを用いた情報収集の対策 Introspectionを無効にする場合は、Field Suggestionも同様に無効化すべき GraphQL開発者Lee Byron氏のコメント ” I would expect that a schema with introspection disabled would also disable didYouMean. I can’t think of a reason why you would want to disable introspection but enable didYouMean or vice versa. https://github.com/graphql/graphql-js/issues/2247#issuecomment-815430294 ” introspectionを無効にしたスキーマはdidYouMeanも無効になることを期待します。 introspectionを無効にしてdidYouMeanを有効にしたい理由や、その逆は思いつかない。 18 / 23

Slide 19

Slide 19 text

Security․Tokyo #2 たくさん悪用方法があって対策が大変… 良い方法ない? 19 / 23

Slide 20

Slide 20 text

Security․Tokyo #2 究極の対策: Persisted Queries 通常の方法 Persisted Queries https://www.apollographql.com/blog/apollo-client/persisted- graphql-queries/ より引用 GraphQLの柔軟性は失われるものの、攻撃者 は自由にクエリを作れなくなる 今までに紹介した攻撃はすべて防げる 本番環境で固定のクエリしか実行しないのであ れば検討する余地あり 本来は帯域節約のために考えられた技術 20 / 23

Slide 21

Slide 21 text

Security․Tokyo #2 おわりに GraphQL特有の機能における悪用方法を紹介した Introspectionを用いた情報収集 Aliasを用いた認証回避・DoS Fragmentを用いたDoS Field Suggestionを用いた情報収集 GraphQLは開発者にとってフレンドリーだが、攻撃者にとってもフレンドリー 不要な機能は無効化しておこう 21 / 23

Slide 22

Slide 22 text

Security․Tokyo #2 参考文献 Black Hat GraphQL 攻撃手法を体系的に学ぶことができる 学んだ結果↓ 2023/4 発売。 約7000円とお高めだが買う価値アリ 22 / 23

Slide 23

Slide 23 text

Security․Tokyo #2 その他の学習リソース https://github.com/flatt-security/mini-ctf 2023/4,7 に開催されたFlatt Security主催のCTF 出題環境が公開されており、Docker Composeでデプロイして解くことができる https://portswigger.net/web-security/graphql あのBurpを作っているPortSwiggerのトレーニングコンテンツ 2023/6に公開されたばかり 23 / 23