Burp SuiteのGraphQL手動検査ツールさわってみた

はじめに
本記事は、Burp Suite 2023.11.1.3の安定版リリースで追加された、GraphQLの手動検査ツール機能に関する紹介記事になります。
原文をご確認されたい方は、公式のリリースノートをご覧ください。
機能紹介
これまでのGraphQLに関する機能では、Burp ScannerによるGraphQLの検査が可能でしたが、手動による検査は(Burpだけで行うなら)GraphQL構文を操作するためのExtenderを利用するしかありませんでした。
いくつかGraphQL用のExtenderはありますが、有名どころだとinQLが挙げられます。
ですが、今回のリリースでExtender無しでGraphQLを操作することができるようになりました。具体的には以下の機能がリリースされています。
- GraphQL リクエストの表示と編集
- イントロスペクションクエリの生成
それぞれどのような機能なのか実際に試してみます。
GraphQL リクエストの表示と編集
GraphQLのエンドポイントにアクセスすると、Burpは自動的にGraphQLエンドポイントを検出するようです。
検出後、GraphQL用のタブが表示・選択できるようになり、GraphQLのシンタックスを解析してくれます。
リクエストをRepeaterに移動させて、QueryやVariablesを改変して送信することができます。

GraphQLタブが表示されている

GraphQLの編集画面
イントロスペクションクエリの生成
イントロスペクションクエリは、GraphQLのエンドポイントリクエストをRepeaterに移し、コンテキストメニューから生成することができます。

生成できるイントロスペクションクエリは、通常のものとlegacyタイプの2種類がありました。
通常のイントロスペクションクエリ
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
locations
args {
...InputValue
}
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
Legacyイントロスペクションクエリ
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation
onFragment
onField
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
イントロスペクションクエリのレスポンスを受け取ることで、コンテキストメニューの「Save GraphQL queries to site map」が有効になります。
サイトマップ登録機能は、イントロスペクションクエリの結果をもとにクエリを解析し、未送信の状態でサイトマップに登録されます。

未送信リクエストは、コンテキストメニューの「Request in browser」で送信することができます。
送信後、サイトマップ上では灰色から白色に変わり、レスポンスも受け取れています。

IDなどのArgumentsが必要なクエリは、セット可能なVariablesを用意してくれます。ただし、Variablesのvalueは空や0の状態なので、手動で変更する必要があります。
例えば、以下の画像はサイトマップに登録されたGraphQLクエリの一部です。

このクエリは、 personID を引数として持っているため、このリクエストをそのまま送信してもpersonID がnullでエラーが返ってきます。

この場合は、Repeaterにリクエストを送り、 personID を変えて送信すると指定したPerson情報を取得することができます。

Repeaterの送信結果
まとめ
イントロスペクションクエリを自動で飛ばさない、サイトマップに登録されるクエリも自動で飛ばさない、Variablesは空や初期値がセットされている点が、人が手動で診断する前提の作りとなっていて、とても診断しやすくなったと感じました。
これまで、クエリドキュメントが公開されているアプリケーションであっても、診断員がドキュメントを見て各クエリを作成するのが大変でした。今回の機能でクエリがほぼ自動でフォーマットとして用意され、診断員は必要な値をVariablesに入れたり、クエリを変更したりといった作業だけで診断が出来るようになったのはとても良いですね。
それではよいBurpライフを!