GraphQLでできたやられサイトで遊んでみる
はじめに
今回は、DVGAというやられアプリを使用して、GraphQL特有の攻撃をいくつか行ってみたいと思います。
準備
先ずは、Dockerのイメージを引っ張ってくる。
docker pull dolevf/dvga
そして、イメージからコンテナを作成
docker run -t -p 5013:5013 -e WEB_HOST=0.0.0.0 dolevf/dvga
これで、http://127.0.0.1:5013/ にアクセスすればDVGAは開く。以下のようなサイトです。
サイトの機能としては、Create Pasteで投稿が作れて、ここで投稿をPrivateかPublicか、どちらで公開する選べるようになってます。それぞれの投稿は、Public Pates , Private Pastesで確認することが出来ます。他にも、Paste(投稿内容擬き)をインポート、アップロードする機能がある事が見て取れます。これで、やられアプリのざっくりとした説明は終わりです。
本編
偵察
ここからは偵察フェーズとして、このサイトを見ていきたいと思います。ポートスキャンとか、そういった類のものと同じフェーズです。ここでは、偵察して何の情報を得たいかというと、エンドポイントであったり、フィンガープリントを元に、何のGraphQLエンジンが動いているのか調査していきます。
それでは実際に調査していきます。今回はgraphw00fというものを使っていこうと思います。落としてきたディレクトリに移動して早速動かしていく。
# エンドポイントをスキャン graphql版gobusterみたいな機能 $ python3 main.py -d -t http://127.0.0.1:5013/ 途中略 [*] Checking http://127.0.0.1:5013// [*] Checking http://127.0.0.1:5013//graphql [!] Found GraphQL at http://127.0.0.1:5013//graphql # 上の結果から、エンドポイントが http://127.0.0.1:5013//graphql である事が分かる # 今度はフィンガープリントモードで動かしてみる GraphQLエンジンを特定 $ python3 main.py -f -t http://127.0.0.1:5013/graphql 途中略 [*] Checking if GraphQL is available at http://127.0.0.1:5013/graphql... [!] Found GraphQL. [*] Attempting to fingerprint... [*] Discovered GraphQL Engine: (Graphene) [!] Attack Surface Matrix: https://github.com/nicholasaleks/graphql-threat-matrix/blob/master/implementations/graphene.md [!] Technologies: Python [!] Homepage: https://graphene-python.org [*] Completed. # Grapheneというエンジンが動いていることが分かる. # 更に、Attack Surface Matrixの項目のURLから、Grapheneに関する情報のまとめも確認できます。
上記の結果から、エンドポイントは htt[p]://127.0.0.1:5013/graphql 、動いているGraphQLエンジンはGrapheneという事が分かりました。
Introspectionを利用した攻撃
更に詳細に調べるために、今度はイントロスペクションクエリを利用しスキーマの情報を取得していきます。このクエリを利用していきます。実際に送ってみると、以下のようなレスポンスが返ってきてスキーマの情報が取得できます。
この取得できた情報を、コピペしてGraphQL Visualizerなどにかけます。すると、よりスキーマ情報が視覚的に理解しやすくなります。以下が見切れていますが、その結果です。実際に試してみると分かりやすいです。
DoS攻撃
重いクエリをバッチ処理で実行
上で調査した内容で、Queryの中にsystemUpdateという項目があるのが分かります。ここで、サーバーにsystemUpdateでアップデートをチェックするクエリを飛ばしてみます。
Burpのレスポンスタイムを見るとかなり処理に時間を要している事が分かります。これを利用すればDoS攻撃ができそうなことが推測できます。確かに、複数回同様のリクエストを飛ばすのも良い気がします。しかしながら、GraphQLにはバッチ処理という機能があるので、こちらを利用して1回のリクエストで複数回queryを呼び出してみたいと思います。今回の場合、ペイロードは以下です。
query systemUpdate { q1: systemUpdate q2: systemUpdate q3: systemUpdate }
こんなレスポンスが返ってきます。これは確かにかなり時間かかりそうだなって感じ
再帰処理するネストされたクエリの送信
貼ると長くなるので、画像で紹介します。以下のように、深くネストされたクエリを送信することで、重い処理を実行させ、レスポンスが遅延していることを確認できます。
GraphQLエラーによる情報開示
送信するクエリに少し情報を与えることで、スキーマの情報をレコメンデーションしてくれます。
脆弱性というよりか、開発者向けの便利機能を利用して、スキーマの情報を少しずつ引き出していく、といったニュアンスが正しいですかね。
例えば、以下のペイロードなんかが今回は使えます。
{"query":"query {system}"}
以下のようなレスポンスが返ってきました。
もう既に、Introspectionの利用で分かってる値では有りますが、情報が出ているのが分かりますね。
一応、下にピックしておきます。
"message":"Cannot query field \"system\" on type \"Query\". Did you mean \"pastes\", \"paste\", \"systemDebug\", \"systemUpdate\" or \"systemHealth\"?"
最後に
以上が、最低でもGraphQLでは確認しておきたい箇所ですね。 他にも、このWebアプリにはXSSや、OS Command Injectionなどが刺さります。時間がある方は試してみても良いかも知れません。