DVGA writeup

4.5K Views

May 08, 23

スライド概要

Damn Vulnerable GraphQL Applicationで遊んでみたノートです。

profile-image

都内で働くセキュリティエンジニア

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

DVGA 2021/5/31 iwama

2.

GraphQLのリクエストについて • HTTPリクエストの操作が必要です。ローカルプロキシツール(Burpやfiddler)を事前にイン ストールしておくことを推奨します。 • GraphQLは独自のフォーマットを利用してリクエストを行います。フォーマットをパースでき る拡張機能やデバッガーがあると便利です。 • 今回はBurpエクステンダーのinQLを使用しました。 • Souce: https://github.com/doyensec/inql • ※ inQL Scannerはうまく動作していませんでした(2021/5/31) • 他の方法として、APIテストツール(insomniaやAltair)を利用するのをおすすめします。 • Insomnia: https://insomnia.rest/ • Altair: https://altair.sirmuel.design/

3.

GraphQLの基礎 GraphQLについて知りたい場合は、公式のガイドが分かりやすいです。 • https://graphql.org/learn/ GraphQLのセキュリティについて知りたい場合は、OWASPのGraphQL Cheat Sheetや、 DVGAのHomeページで紹介しているリソースを参考にするといいと思います。 • https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html

4.

問題について Damn Vulnerable GraphQL Application(DVGA) • Source: https://github.com/dolevf/Damn-Vulnerable-GraphQLApplication • 起動方法: • $ docker run -t -p 5000:5000 -e WEB_HOST=0.0.0.0 dolevf/dvga • ブラウザでhttp://localhost:5000にアクセス • 注意: • 問題形式にはなっていますが、FLAG形式ではありません。 • シナリオが用意されており、シナリオ毎に脆弱性を確認してきます。

5.

シナリオ #1 • DoS • Batch Query Attack • Deep Recursion Query Attack • Resource Intensive Query Attack • Field Duplication Attack • Aliases based Attack • 情報漏洩 • GraphQL Introspection • GraphiQL Interface • GraphQL Field Suggestions • Server Side Request Forgery • コード実行 • OS Command Injection #1 • OS Command Injection #2

6.

シナリオ #2 • インジェクション • Stored Cross Site Scripting • Log spoofing / Log Injection • HTML Injection • 権限昇格・権限迂回 • GraphQL Interface Protection Bypass • GraphQL Query Deny List Bypass • その他 • GraphQL Query Weak Password Protection • Arbitrary File Write // Path Traversal

7.

Batch Query Attack 問題文 GraphQL supports Request Batching. Batched requests are processed one after the other by GraphQL, which makes it a good candidate for Denial-ofService attacks, as well as other attacks such as Brute Force and Enumeration. If a resource intensive GraphQL query is identified, an attacker may leverage batch processing to call the query and potentially overwhelm the service for a prolonged period of time. The query systemUpdate seems to be taking a long time to complete, and can be used to overwhelm the server by batching a system update request query.

8.

Batch Query Attack シナリオ解説 GraphQLは、単体のGraphQLリクエストで複数のクエリを送信する機能を持っています。こ れをバッチ処理と呼びます。 バッチ処理を悪用して、重い処理行うクエリ複数発行することでDoSを引き起こさせます。 攻略方法 重い処理を探し出し、バッチ処理を併用してレスポンスが遅くなるのを確認してください。

9.

Batch Query Attack – Solution 1. イントロスぺクションクエリなどでアクセス可能なクエリを調査する。GraphQL Introspection項を参照。 2. systemUpdateやsystemDiagnostics、systemHealthなどシステム機能があること が確認できる。 3. systemUpdateを実行し、めっちゃ時間かかることを確認する。

10.

Batch Query Attack

11.

Batch Query Attack 4. バッチ処理でたくさん送る(レスポンスタイムには影響しない様子)

12.

Deep Recursion Query Attack 問題文 In GraphQL, when types reference eachother, it is often possible to build a circular query that grows exponentially to a point it could bring the server down to its knees. Countermeasures such as max_depth can help mitigate these types of attacks. The max_depth functionality acts as a safeguard, and defines how deep a query can get, ensuring deeply constructed queries will not be accepted by GraphQL. The application offers two types, namely Owner and Paste, which reference eachother (an owner has a paste, and a paste has an owner), allowing a recursive query to be executed successfully.

13.

Deep Recursion Query Attack シナリオ解説 相互に参照できるオブジェクトが存在する場合、再帰クエリ(循環クエリとも呼ぶ)を実行するこ とができます。 ネストの深い再帰クエリを実行し、リソースを大量に消費させDoSを引き起こさせます。 攻略方法 相互参照できるオブジェクトを探し出し、再帰クエリによってレスポンスが遅くなるのを確認して ください。

14.

Deep Recursion Query Attack – Solution 1. 相互参照しているオブジェクトを探す。 2. PasteObjectとOwnerObjectが相互参照していることが分かる。

15.

Deep Recursion Query Attack – Solution 3. 再帰クエリでネストを深く書いて送る

16.

Resource Intensive Query Attack 問題文 Sometimes, certain queries may be computationally more expensive than others. A query may include certain fields that would trigger more complex backend logic in order to fulfill the query resolution. As attackers, we can abuse it by calling these actions frequently in order to cause resource exhaustion. In GraphQL, a concept called Query Cost Analysis exists, which assigns weight values to fields that are more expensive to resolve than others. Using this feature, we can then create an upper threshold to reject queries that are expensive. Alternatively, a cache feature can be implemented to avoid repeating the same request in a short time window.

17.

Resource Intensive Query Attack シナリオ解説 よくわからず。 複雑なクエリは時としてリソース消費が高くなる場合があります。悪用されることで、DoSを引き 起こします。 攻略方法 よくわからず。Batch Query Attackを一緒っぽい。

18.

GraphQL Introspection 問題文 GraphQL Introspection is a special query that uses the __schema field to interrogate GraphQL for its schema. Introspection in itself is not a weakness, but a feature. However, if it is made available, it can be used and abused by attackers seeking information about your GraphQL implementation, such as what queries or mutations exist. It is recommended to disable introspection in production to avoid data leakages. Note: If introspection query is disabled, attackers may fall back to using the Field Suggestion feature to understand what queries and fields are supported by your GraphQL. Refer to Information Disclosure :: GraphQL Field Suggestionsattack for more information.

19.

GraphQL Introspection シナリオ解説 GraphQLイントロスぺクションクエリは、GraphQL Schemaを問い合わせるのに用いられ、 利用可能な型やクエリを調べるのに役立ちます。 悪用されることで、対象のGraphQL実装に関する情報を取得することできます。 攻略方法 イントロスぺクションクエリを実行してGraphQL実装に関する情報を集めてください。 • 実行可能なクエリ • クエリ呼び出しに必要な引数や引数の型など

20.

GraphQL Introspection – Solution 1. イントロスぺクションクエリを叩く。クエリはOWASPなどを参考に。 • 2. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/12API_Testing/01-Testing_GraphQL Burpから送信してもよいが確認がしにくいので、inQLの「Send to graphiQL」でgraphiQLに送ってから確認したほうが分か りやすい。

21.

GraphQL Interface 問題文 GraphQL has a an Integrated Development Environment named GraphiQL (note the i) that allows constructing queries in a friendly user interface. GraphiQL is usually found in paths such as: /graphiql or __graphiql, however, it can be in other places too. You can use this Nmap NSE script to enumerate GraphiQL endpoints.

22.

GraphQL Interface シナリオ解説 GraphQLのIDEで有名なGraphiQLというものがあります。 GraphiQLは、デフォルトでは/graphiqlにアクセスすることで利用可能です。 攻略方法 GraphiqlのUIにアクセス

23.

GraphQL Interface – Solution http://localhost:5000/graphiqlにアクセス

24.

GraphQL Field Suggestions 問題文 GraphQL has a feature for field and operation suggestions. When a developer wants to integrate with a GraphQL API and types an incorrect field, as an example, GraphQL will attempt to suggest nearby fields that are similar. Field suggestions is not a vulnerability in itself, but a feature that can be abused to gain more insight into GraphQL's schema, especially when Introspection is not allowed.

25.

GraphQL Field Suggestions シナリオ解説 GraphQLには間違ったフィールドを入力したときのサジェスト機能が備わっています。 イントロスぺクションクエリが許可されていない場合に、サジェスト機能はGraphQLの実装を知 るための手がかりになります。 攻略方法 サジェスト機能を確認してください

26.

GraphQL Interface – Solution 適当に間違える

27.

Server Side Request Forgery 問題文 The GraphQL mutation importPaste accepts arbitrary host, port and scheme to import pastes from and does not restrict input such as localhost or other internal servers from being used. This may allow forging requests on behalf of the application server to target other network nodes.

28.

Server Side Request Forgery シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

29.
[beta]
Server Side Request Forgery – Solution
1. 正常リクエスト時のimportPasteクエリを確認
{

"query":"mutation ImportPaste ($host: String!, $port: In
t!, $path: String!, $scheme: String!) {
importPaste(host: $host, port: $port, path: $path, s
cheme: $scheme) {
result
}
}",
"variables":{
"host":"pastebin.com",
"port":443,
"path":"/raw/m6GHCKJ2",
"scheme":"https"
}
}
}

30.

Server Side Request Forgery – Solution 2. Host, port, path, schemeを改ざんしてSSRF

31.

OS Command Injection #1 問題文 The mutation importPaste allows escaping from the parameters and introduce a UNIX command by chaining commands. The GraphQL resolver does not sufficiently validate the input, and passes it directly into cURL.

32.

OS Command Injection #1 シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

33.

OS Command Injection #1 – Solution • importPasteはOSのcurlコマンドを叩いてるので、パイプラインなどでOScmdiが可能

34.

OS Command Injection #2 問題文 The query systemDiagnostics accepts certain UNIX binaries as parameters for debugging purposes, such as whoami, ps, etc. It acts as a restricted shell. However, it is protected with a username and password. After obtaining the correct credentials, the restricted shell seems to be bypassable by chaining commands together.

35.

OS Command Injection #2 シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

36.

OS Command Injection #2 – Solution 1. GraphQL Query Weak Password Protectionの項で説明している方法で管理者の クレデンシャルを取得する 2. 奪取したクレデンシャルを使ってOSコマンドを実行する

37.

Stored Cross Site Scripting 問題文 The GraphQL mutations createPaste and importPaste allow creating and importing new pastes. The pastes may include any character without any restrictions. The pastes would then render in the Public and Private paste pages, which would result in a Cross Site Scripting vulnerability (XSS).

38.

Stored Cross Site Scripting シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

39.

Stored Cross Site Scripting – Solution タイトルや本文がエスケープされてないので、スクリプトがそのまま挿入される Public PastesページにアクセスするとXSSが確認できる。

40.

Log Injection 問題文 GraphQL actions such as mutation and query have the ability to take an operation name as part of the query. Here is an example query that uses MyName as an operation name: query MyName { getMyName { first last } } The application is keeping track of all queries and mutations users are executing on this system in order to display them in the audit log. However, the application is not doing a fair job at verifying the operation name.

41.

Log Injection シナリオ解説 GraphQLリクエストをサーバ側で管理するために、リクエストを識別できるOperation Nameを設定することができます。サーバ側はOperation Nameと共にリクエスト内容をログ に記録することで、デバッグや監視が容易になります。 Operation Nameはユーザ側で自由に変更できるため、Operation Nameのみでログ管理 している場合は、不正ログが挿入される恐れがあります 攻略方法 Operation Nameを改ざんし、不正リクエストをログに残さないようにしてください。

42.

Log Injection – Solution Auditページを確認すると GraphQL Operationがリストに記載されている GraphQLのOperation Nameを改ざんして送る

43.

Log Injection – Solution

44.

HTML Injection 問題文 Similarly to the Cross Site Scripting problem, a paste can also include HTML tags that would render in the application, resulting in an HTML injection.

45.

HTML Injection シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

46.

HTML Injection – Solution XSSやSSRFでhtml読み込むのと同じ

47.

GraphQL Interface Protection Bypass 問題文 GraphiQL is available at the path /graphiql with a poorly implemented authorization check.

48.

GraphQL Interface Protection Bypass シナリオ解説 GraphiQLは権限確認が不十分なのでバイパスが可能です。 攻略方法 GraphiQLの権限確認を回避し、GraphQLクエリを実行してください。

49.

GraphQL Interface Protection Bypass – Solution Cookieのenvをgraphiql:enableに書き換えてbase64にする

50.

GraphQL Query Deny List Bypass 問題文 Creating an allow-list or deny-list for GraphQL is a common technique to prevent malicious queries from being resolved by GraphQL. ⚫ By defining an allow-list, the application server will have a "known good" queries it will allow, and reject anything else. ⚫ By defining a deny-list, the application server will have a "known bad" queries it will reject, and allow anything else. In general, the allow-list approach is easier to maintain and less error-prone, since we only allow certain things we trust. It does not mean it cannot have flaws too. The application has a deny-list mechanism implemented that attempts to reject Health queries using the systemHealth query. The problem with this mechanism is that it does not take into consideration queries can have operation names.

51.

GraphQL Query Deny List Bypass シナリオ解説 allow-listやdeny-listを作成することで、実行できるクエリを定義するのが一般的です。 (GraphQLで定められている仕様ではないです) Operation Nameでクエリの確認をしている場合、このメカニズムをバイパスすることができ ます。 攻略方法 OperationNameを変えて、クエリを実行できることを確認する。

52.

GraphQL Query Deny List Bypass – Solution • systemHealthを実行しようとしてもDeny Listに入っているためはじかれる

53.

GraphQL Query Deny List Bypass – Solution • Operation Nameでチェックしているので、適当なOperation Nameに変更する

54.

Arbitrary File Write // Path Traversal 問題文 The mutation uploadPaste allows uploading pastes from the user's computer by specifying the file along with the filename. The pastes are then stored on the server under a dedicated folder. The filename argument allows any string, effectively providing the ability to write the file to any location on the server's filesystem by traversing folders using ../../

55.

Arbitrary File Write // Path Traversal シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

56.

Arbitrary File Write // Path Traversal – Solution uploadPasteクエリはパストラバーサルの脆弱性がある。 Dockerのexecコマンドでファイルが作られているか確認

57.

GraphQL Query Weak Password Protection 問題文 The query systemDiagnostics is an administrative functionality that allows running a subset of system commands on the server. The query is governed by a username and password before processing the command. The password is weak, and the server has no rate limiting protections. This allows attackers to easily conduct brute force attacks against the server.

58.

GraphQL Query Weak Password Protection シナリオ解説 アプリケーションロジックに脆弱性がある場合、 GraphQLも既存のアプリと同様に脅威に晒さ れます。 攻略方法 脆弱性を探してください。

59.
[beta]
GraphQL Query Weak Password Protection – Solution
systemDiagnosticsには、パスワード保護がかかってないのでブルートフォースが可能
import requests
url = "http://localhost:5000/graphql"
proxies = {"http": "http://localhost:8080"}
headers = {"Content-Type": "application/json"}
query = {"query": '{{ "query" : "query {{systemDiagnostics(username:¥¥"admin
¥¥", password:¥¥"{}¥¥", cmd:¥¥"ls¥¥")}}","variables":null }}'}
wordlist = ['changeme', 'password54321', 'letmein', 'admin123', 'iloveyou',
'00000000']
for word in wordlist:
res = requests.post(url, data=query["query"].format(word), proxies=proxi
es, headers=headers)
print("[{}]: {}".format(word, res.text))

60.

GraphQL Query Weak Password Protection – Solution systemDiagnosticsには、パスワード保護がかかってないのでブルートフォースが可能