現場のエンジニア諸君、今日も泥臭い運用お疲れ様。
「暗号化してるから大丈夫」という言葉を、セキュリティの現場で何度聞いたことか。だが、その安心感こそが最大の脆弱性だ。
今日取り上げるのは「保存時暗号化(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(初期化ベクトル)の使い回しや、鍵のハードコーディングは、攻撃者が最も好む「設定ミス」だ。
今日のコードを参考に、君たちのプロダクトの守りをもう一段階強固にしてほしい。何か不明点があれば、コードレビューの際に遠慮なく聞いてくれ。健闘を祈る。
コメント