【実務・中級編】 暗号化データの保存における「保存時暗号化(Encryption at Rest)」のベストプラクティス – 暗号理論・認証基盤 & エンドポイントセキュリティ防御ガイド

現場のエンジニア諸君、今日も泥臭い運用お疲れ様。
「暗号化してるから大丈夫」という言葉を、セキュリティの現場で何度聞いたことか。だが、その安心感こそが最大の脆弱性だ。

今日取り上げるのは「保存時暗号化(Encryption at Rest)」だ。データベースのディスクを暗号化して「はい完了」と思っているなら、君は攻撃者にカモにされている可能性がある。なぜなら、特権IDを奪取した攻撃者は、暗号化されたディスクの中身を「OSレベルでマウントされた平文データ」として読み取れるからだ。

今回は、透過的暗号化(TDE)とアプリケーション層での暗号化をどう使い分け、どこに防壁を築くべきかを、現場の視点で叩き込む。

—

1. なぜ「TDE(透過的暗号化)」だけでは不十分なのか

TDE(Transparent Data Encryption)は、データベースエンジンがディスク書き込み時に自動で暗号化を行う仕組みだ。AWS RDSの「暗号化」などもこれに当たる。

  • TDEの役割: 物理ディスクの盗難や、クラウドプロバイダーのストレージ切り離しによる情報漏洩を防ぐ。
  • 盲点: データベースに接続できるアプリケーション、あるいは「DB管理者権限」を奪取した攻撃者には、TDEは無力だ。SELECT * FROM users; と叩けば、そこには平文が流れてくる。

教訓: TDEは「物理レベルの防御」であり、「データそのものの機密性」は担保していないと心得るべきだ。

—

2. 実戦的アプローチ:フィールドレベル暗号化

クレジットカード番号や個人情報など、流出が許されない「最重要データ」に関しては、アプリケーション層で暗号化してからDBに保存する。これが「フィールドレベル暗号化」だ。

これを行えば、万が一DBのダンプファイルが流出しても、攻撃者の手元には「解読不能なゴミ」しか残らない。

Pythonによる実装サンプル(AES-256-GCM)

現代の暗号化において、古い CBC モードや ECB モードは使うな。必ず認証付き暗号である GCM を使用すること。

import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

# 鍵管理の鉄則: 鍵はコードにハードコーディングせず、AWS KMSやHashiCorp Vaultから取得する
def encrypt_data(plain_text, key):
    aesgcm = AESGCM(key)
    nonce = os.urandom(12)  # 毎回ユニークなnonceを生成(これがないと暗号が解析される)
    ciphertext = aesgcm.encrypt(nonce, plain_text.encode(), None)
    # nonceと暗号文をセットで保存する必要がある
    return nonce + ciphertext

def decrypt_data(encrypted_data, key):
    nonce = encrypted_data[:12]
    ciphertext = encrypted_data[12:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(nonce, ciphertext, None).decode()

# 使い方例:
# key = AESGCM.generate_key(bit_length=256)
# encrypted = encrypt_data("極秘データ", key)

—

3. 暗号化を成功させるための「鍵管理」の極意

暗号化において最も難しいのはアルゴリズムではなく、「鍵の管理」だ。コードの中に鍵をベタ書きしているエンジニアを見つけたら、即座に修正を命じてほしい。

AWS KMS を用いた鍵保護の推奨設定

アプリケーションからは、KMSにアクセスして「データ暗号化鍵(DEK)」を生成させるのがベストプラクティスだ。

1. IAMポリシーで権限を最小化: アプリケーションサーバーのロールには、kms:Encrypt と kms:Decrypt のみを許可する。
2. キーローテーション: KMSの自動ローテーションを有効にしておく。

以下は、IAMで特定のキーのみにアクセスを制限するポリシーの断片だ。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:Encrypt"
      ],
      "Resource": "arn:aws:kms:ap-northeast-1:123456789012:key/your-key-id"
    }
  ]
}

—

4. 最後に:現場のエンジニアへ

セキュリティは「どこか一点を守れば終わり」ではない。

1. ディスクの保護: TDEで物理的な安全を確保。
2. データの保護: アプリ層でフィールドレベル暗号化を行い、DB管理者の特権攻撃を無効化。
3. 鍵の保護: KMS等の専用サービスで鍵を分離管理。

この多層防御が構築できて初めて、「暗号化している」と胸を張れる。

「忙しいから」「面倒だから」という言い訳は、次回のインシデントの引き金になる。特に、nonce(初期化ベクトル)の使い回しや、鍵のハードコーディングは、攻撃者が最も好む「設定ミス」だ。

今日のコードを参考に、君たちのプロダクトの守りをもう一段階強固にしてほしい。何か不明点があれば、コードレビューの際に遠慮なく聞いてくれ。健闘を祈る。

コメント

タイトルとURLをコピーしました