GraphQL — Common vulnerabilities & how to exploit them から学ぶ

ソース:

the-bilal-rizwan.medium.com

脆弱性:GraphQL

 

訳:

GraphQL が何なのか知らない人のために説明すると、そのリクエストは次のようになります。 

 

GraphQL サンプルリクエス

中括弧と \n 文字がいくつか含まれています。
そのようなものが表示された場合は、おそらく GraphQL です。
まず、GraphQL が実際に何であるかを理解することから始めましょう。
これがより良いフォームエクスプロイトに役立つことを知っています。

 

GraphQLとは何ですか?

簡単に言えば、GraphQL は REST や SOAP のような代替 API 標準です。
これは基本的に、API と対話したり、API を介してバックエンドからデータを取得したりするために使用される API のクエリ言語です。
REST API で実行できることはすべて実行できますが、より効率的かつ制御された方法で実行できます。
GraphQL は、必要以上のデータを取得したり、呼び出しごとに新しいエンドポイントが必要になったりするなど、REST の使用中に直面する多くの問題を解決します。

 

次の例では、GraphQL と REST API の違いが明確になります。

REST API では通常、次のようにユーザーデータを取得するために /users/<id> エンドポイントを使用します。
第二に、次のようなことが起こる可能性があります。 /users/<id>/postsユーザーのすべての投稿を返すエンドポイント。
3 番目のエンドポイントは、 /users/<id>/followersユーザーごとのフォロワーのリストを返します。

 

REST API機能

ただし、GraphQL には、具体的なデータ要件を含むクエリを送信するエンドポイントが 1 つだけあり、サーバーはデータ要件で応答します。
システムからユーザー ID を取得したいとします。
次のようにクエリを作成できます。 

 

IDの取得

では、ユーザーのメールアドレスも必要な場合はどうなるでしょうか?
REST API とは異なり、同じエンドポイントの新しい行でリクエストがサーバーに送信されることを指定するだけで済みます。
これは非常に簡単です。

 

 

名前も必要な場合はどうすればよいでしょうか? きっと今なら理解できるようになったと思います。 

 

 

そして、それが Graphql の優れた点であり、必要なものをきめ細かい方法で指定するだけです。
GraphQL が何なのかを理解したところで、次に進みましょう。

 

GraphQL でよくある構成ミス

ここで理解すべきことは、GraphQL は他の REST API と同様、REST API が受けやすい攻撃と同じ多くの攻撃に対して脆弱であるということです。
以下にその一部を列挙しますが、最も興味深いこと、そしてこの投稿全体を作成した理由は、悪名高い イントロスペクション クエリのバグです。

 

イントロスペクション クエリ: 簡単に言えば、サーバーに GraphQL バックエンド スキーマをクエリし、完全なドキュメントとバックエンドで使用できる API 呼び出しのリストを取得する方法です。
これは本来、内部で使用することを目的としています。 

 

イントロスペクションクエリは内部でのみ許可されるべきであり、一般公開されるべきではありません。
バックエンド API ドキュメント全体とサーバー上で利用可能な呼び出しを取得できた場合、多くの場合、それは非常に危険になる可能性があります。
内部でのみ使用される API 呼び出しを入手できたら、有効にするための呼び出しが見つかるかもしれません。
デバッグやユーザーを削除するための API 呼び出しなどにより、バックエンド全体を取得できる場合、非常に多くの損害が発生する可能性があります。 

 

これがどのように行われるかを見てみましょう。

 

サーバーの GraphQL イントロスペクションの構成ミスをテストするには:
1) サーバーに送信されている HTTP リクエストをインターセプトします。
2) 投稿コンテンツ/クエリを汎用イントロスペクション クエリに置き換えて、バックエンド スキーマ全体を取得します。
3) スキーマを視覚化して、魅力的な API 呼び出しを収集します。
4) 興味深いと思われる可能性のある GraphQL 呼び出しを作成し、ハックしてください。

ターゲット Web アプリが GraphQL 呼び出しを行っていると仮定すると、次のように GraphQL Introspection クエリを使用してそのクエリを簡単に変更できます。

 

オリジナルAPI

 

元の API 呼び出し

GraphQL イントロスペクション クエリのバックエンド スキーマの漏洩

POST の内容を次のクエリに置き換えるだけです。

 

 

これを実行すると、応答が非常に大きくなり、理解しにくくなる可能性があります。 スキーマを理解する最良の方法は、それを視覚化することです。 これを行うには、応答本文全体をコピーし、このWeb サイト https://apis.guru/graphql-voyager/ を使用して、「スキーマの変更」ボタンをクリックし、「イントロスペクション」タブに移動して、そこにイントロスペクション クエリを貼り付けます。

 

 

そこにスキーマを貼り付けた後、[表示] をクリックすると、バックエンド全体と利用可能な API 呼び出しが視覚的に表示されます。 

 

GraphQLのバックエンドスキーマ

API 呼び出しのリスト全体が手に入ったので、それを調べて、悪用される可能性のある機密性の高い API 呼び出しがあるかどうかを簡単に確認することができます。 これは、GraphQL バックエンドで見つかった最も一般的なタイプのバグであり、非常に重大なシナリオにつながる可能性があります。

 

この時点までは、このバグの本当の影響を完全には同期していないのではないかと感じました。そのため、例を挙げてみましょう。
graphql スキーマの見方とgraphQL クエリの作成方法をすでに知っている人は、これ以上読み進める必要はありません。
非常に便利ですが、スキーマを視覚化して、センシティブに見える何かを見つけてそれを悪用したい人、または単に内省の真の影響を理解したい人にとっては、先に読み進めてください。 

 

GraphQL クエリ形成の学習:
GraphQL には 3 つの基本的なタイプのクエリまたはコンポーネントがあります

Queries
REST API の GET リクエストと同様に、クエリを使用してデータをフェッチします。

Mutation
データの作成、編集、削除に使用します。

Subscriptions
リアルタイム通信に使用されます。 これには焦点を当てません。

すべてのgraphQLクエリは、改行と中括弧を含むjson形式で記述されます。
例として 2 つの機能を持つ Web アプリケーションを使用してみましょう
1) ユーザーをリストする
2) ユーザーを追加する
次に、イントロスペクション クエリを使用してアプリケーション内のバグを見つけます。これは Web アプリでよく見られるものです。

 

ユーザーをリストするための GraphQL 呼び出し

上の図は、通常現在表示されているものです。
これを改善するには、JSON Beautifier のようなBurpプラグイン、あるいは GraphQL Raider として知られる GraphQL に特化したプラグインを使用できます。
インストールすると、GraphQL のどこにでも JSON beautifer と同じようなタブが表示されます。 

 

上記ははるかに良い方法で表示できるようになりました

 

 

有効な画像から、graphQL クエリ構造を簡単に理解できるはずです。

 

query{
<FUNCTION NAME>
{
<COMPONENT>
<COMPONENT>
}
}

 

そのような単純な。
それがクエリの仕組みです。 それがウェブサイトが提供する最初の機能です
このアプリではユーザーを追加することもできますので、試してみてください。 

 

 

 

さて、げっぷを通じてこれらの呼び出しを表示し、フロントエンドのボタンをクリックして呼び出しを生成することができますが、どうすればもっと魅力的なものを見つけることができるでしょうか?
それでは、イントロスペクション クエリを試してみましょう。 

 

イントロスペクション クエリを使用して応答データをコピーし、voyager に貼り付けます。 

 

イントロスペクションクエリ

 

これはテスト アプリであるため、スキーマは非常に小さいですが、画像をよく見てください。
これは、図でわかるように、イントロスペクションを使用して機密性の高いものを見つける方法の非常に核心的で基本的な例です。
ユーザー関数には多くのフィールドがあります。
ID、メールアドレス、名前などはすでに知っていますが、ちょっと待ってください…この uPassword は何ですか。 取得してみましょう。 

 

 

おお!! バックエンドからパスワードを取得しただけです。
なぜこのようなことができたのでしょうか?
バックエンドにはパスワードフィールドがあり、それをgraphql呼び出しで使用できるため、これはイントロスペクションを通じてのみ可能でした。 

 

オンラインのgraphQL視覚化には小さな問題があります。
Mutation は表示されませんが、気付きましたか?
そうですね、あなたは鋭い目を持っています。
私自身、すぐには気づかなかったので、それを知るまでに長い時間がかかりました。いったいどれだけのバグを見逃してしまったのだろうと不思議に思っています。
悲しいことにそれについては何もできません。

ここでの問題は、Mutation を含む完全なスキーマをどのようにリストするかということです。Google で調べたところ、これを見つけました。

 

 

ここで、graphql Playground の優れた点は、実際にイントロスペクション クエリを利用し、そこからドキュメントを作成することです。

あなたがしなければならないのは、アプリケーションをダウンロードして、持っているクッキーと一緒にgraphqlエンドポイントのURLに貼り付けるだけです。

 

 

パラメータとともに変異を表示するには 左側の [ドキュメント] > [変異] をクリックすると、パラメータとともに変異を表示できます。
次の関数で関数を確認できます。
addUser
& delUserそしてパラメータを見ることができます id,email,name,uPassword,avatarUrl上記の知識を使用して、これを使用してクエリを作成できます。 

 

 

しかし、これも視覚化したいと思います。 ここで行うことは、[ドキュメント] タブをクリックして、SDL 形式でスキーマをダウンロードすることです。 

 

 

スキーマを取得したら、 https://app.graphqleditor.com/に移動します。
サインインして「マイ プロジェクト」に移動し、新しいプロジェクトを追加します 

 

 

プロジェクトに名前を追加し、次のようにスキーマを貼り付けます。

 

 

または、上部のアップロード ボタンをクリックして、graphql-playground を使用してダウンロードした schema.graphql sdl ファイルをアップロードすることもできます。 

 

 

スキーマがアップロードされたら、左側のメニューの最後のアイコンをクリックします。 

 

 

さて、突然変異部分を見ると、フロントエンドでは利用できない別の関数がわかります。
delUser
関数を実行すると、ID の引数を 1 つ受け取ることもわかります。試してみましょう。
ユーザー 1 を削除しましょう。

視覚化を利用してこのように引数を渡します

 

 

 

シンプルですね? そうでない場合は、上記の突然変異の部分をもう一度読んでみてください。きっと理解できると思います。 delUser クエリを実行した後、ユーザーを再度リストします。

 

DelUser のgraphQL 呼び出し

 

ご覧のとおり、ユーザー 1 は削除されています。
これは、イントロスペクションを使用して発見できるものの簡単な例にすぎません

ボーナス:graphql-playground に Cookie を追加する方法

リクエストの多くは Cookie を設定する必要があるため、スキーマを見つけて視覚化した後で burp を使用してリクエストを作成するというアイデアは素晴らしいと思いました。
graphql-playground を使用する方が便利です。
これはさまざまな点で役に立ちます。
ほとんどの場合、スキーマを取得してイントロスペクションを実行するためにも Cookie が必要になります。
残念ながら、Graphql-playground の [Http-Header] タブで Cookie を設定する方法はありません。
設定できるのはカスタム ヘッダーのみで、開発者によって制限されている「Cookie」ヘッダーは設定できません。
しかし、これらの制限を回避するハッキングは常に存在します。
graphql を使用して Cookie を設定し、リクエストを監視するには、すべてのgraphql トラフィックを burpsuite からリダイレクトすることをお勧めします。
これを行うには、まず、ローカルホスト上の特定のポートからのすべての受信トラフィックをターゲットにリダイレクトする新しいリスナーをセットアップする必要があります。
例: トラフィックが次のようになると想像してください。 https://example.com/graphqlburp > プロキシ > オプションに移動し、リスナーの下で追加をクリックし、任意のポートを追加します。

 

 

次に、「リクエスト処理」をクリックし、ターゲットのホスト/ドメインを「ホストへのリダイレクト:」に追加し、「TLS の使用を強制する」をクリックすると、自動的にポート 443 が入力され、「OK」をクリックします。

 

 

図のように新しいリスナーが追加されます

 

 

OK、クックは Graphql プレイグラウンドに移動するだけで、すべてのリクエストがターゲットではなく http://localhost:5555/graphql-endpoint に送信されるようになります。 Burp はリクエストをキャッチし、ターゲットホストにリダイレクトします。

 

 

次に、テストで頻繁にカスタム ヘッダーを追加する必要があるため、リクエストにカスタム ヘッダーを追加してみます。
[HTTP ヘッダー] をクリックして、カスタム ヘッダーを JSON 形式で追加するだけです 

 

 

 

そのような単純な。 しかし、ここでの問題は、開発者が制限している「Cookie」ヘッダーを追加できないことです。そのため、これを回避するには、ダミーヘッダーを追加し、その後、burp の一致と置換ルールを使用して、次のように置き換える必要があります。それは Cookie ヘッダーを使用します。
ヘッダーを実行するには、 Cookie 必要があります。 まずダミー ヘッダーを追加し、それをCookiex と呼び、必要な値を指定する
次に、げっぷに移動し、[プロキシ]タブ > [オプション] > [一致と置換] > [追加]に移動し、タイプで [リクエスト ヘッダー] を選択し、「Cookiex」と一致し、Cookie に置き換えます。 [OK] をクリックすると、準備は完了です。

 

 

「Cookiex」ヘッダーを使用してリクエストを送信すると、実際のリクエストが Cookie ヘッダーを使用して送信されることがわかります。

 

 

Graphql のその他のバグ:

他の REST API と同様に、GraphQL は、たとえば、そこに存在するすべての API バグに対して脆弱です。
1) IDOR
ID を見ればどこで何をすべきかわかるでしょう。このバグは GraphQL とは関係なく、認可のバグです。
2) ブルートフォース
OTP を参照してください。 または MFA コードでレート制限をチェックする
3) SQLインジェクション
はい、正しく読みました。GraphQL はアプリに基本的なバグがないという意味ではないので、常にチェックしてください。 しかし、現在では GraphQL API の多くが MongoDB に接続されていることに気付きました。そのため、SQL インジェクションを使用しないことに慣れておく必要があります。 (はい、それは問題です)
4) CSRF
5) DOS 用のネストされた Graphql クエリ ( https://voidsec.com/graphql-security-overview-and-testing-tips/ )

GraphQL には、イメージできるその他の API バグが存在します。

この知識を利用して、管理者のみが表示できる Web アプリでユーザー PII を表示することができ、わずか数百ドルの少額の報奨金を獲得しました。

 

 

 

ほなほな。