境界防御は死んだ。マイクロセグメンテーションで「侵入前提」の防衛線を敷け
現場のエンジニア諸君、お疲れ様。今日もどこかで誰かが「うちはVPCで囲っているから大丈夫」なんて楽観的なことを言っているだろうが、ハッキリ言おう。境界防御だけのセキュリティは、もはやザルだ。
一度WebサーバがRCE(リモートコード実行)を食らえば、そこは攻撃者の拠点(Pivot)となる。ネットワークがフラットなままなら、攻撃者はそこを足がかりにデータベースや管理用APIへ自由に横展開(ラテラルムーブメント)してくる。
今日は、教科書的な「セグメント分けましょう」というお題目を通り越して、「侵入されても被害を最小化する」ための、現場直結のマイクロセグメンテーション戦略を伝授する。
—
1. 攻撃者の視点:なぜ「フラットなネットワーク」は地獄なのか
攻撃者は、最初の足がかりを得た後、まず何をすると思う? 答えは nmap や arp -a じゃない。彼らは、Webサーバの環境変数からAWSのメタデータサービス(IMDSv2)を叩き、IAMロールの権限を盗み、社内の内部ネットワークを「偵察」する。
もし君のWebサーバとDBが同じサブネットにあり、セキュリティグループ(SG)で「VPC内全許可」なんて設定をしていたら、攻撃者は「見えない壁」を突破したも同然だ。攻撃者は、認証不要な内部APIや、パッチ未適用の管理画面を狙い撃ちにする。これが「ラテラルムーブメント」の正体だ。
—
2. 実践:AWSにおける「最小権限」のSG設計
VPCのサブネット分離は当たり前として、肝心なのは「SGによる通信のホワイトリスト化」だ。
よくあるダメな例は「HTTP/HTTPSをどこからでも許可(0.0.0.0/0)」した後に、内部通信も「同じSG内なら許可」とすること。これでは横展開を止められない。
推奨:階層別セキュリティグループの実装
以下の通り、役割ごとにSGを細分化し、「送信元をIPアドレスではなくSG IDで指定」するのが鉄則だ。
- Web-SG: 80/443をインターネットから許可。
- App-SG:
Web-SGからのトラフィックのみ許可。 - DB-SG:
App-SGからのDBポート(3306/5432等)のみ許可。
Terraformによる定義例(インフラのコード化)
# DBサーバ用のセキュリティグループ定義
resource "aws_security_group" "db_sg" {
name = "db-security-group"
description = "App-SGからのアクセスのみ許可"
vpc_id = var.vpc_id
# ここが重要:IPではなく「App-SG」のIDをソースとして指定する
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app_sg.id]
description = "App-SGからの通信のみ許可(ラテラルムーブメント阻止)"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
—
3. アプリケーション層でのガードレール:WAFによる保護
ネットワークレベルだけでなく、アプリケーション層でも「想定外の通信」を弾く必要がある。特に最近は、生成AI系のAPIを利用するアプリが増えているが、これが「SSRF(サーバーサイド・リクエスト・フォージェリ)」の温床になりやすい。
curl や file_get_contents で外部URLを直接叩くロジックには、必ずバリデーションを噛ませろ。
PHPでの実装例:URLホワイトリストによるSSRF対策
<?php
/**
* 外部API呼び出し時のSSRF対策
* 信頼できるホスト以外へのリクエストを遮断する
*/
function safe_remote_request($url) {
$allowed_hosts = ['api.trusted-service.com', 'ai-model.provider.com'];
$parsed_url = parse_url($url);
// ホスト名がホワイトリストに含まれているかチェック
if (!in_array($parsed_url['host'], $allowed_hosts)) {
throw new Exception("不正なホストへのリクエストを検知しました: " . $parsed_url['host']);
}
// ここから先で実際の通信処理を行う
// ...
}
?>
—
4. 最後に:なぜ現場でこれが守れないのか
現場でこの設計が崩れる最大の理由は「運用コスト」だ。SGを細かく分けすぎると、開発時に「あれ、繋がらない!」というトラブルシューティングが増える。
しかし、セキュリティチーフとして言わせてもらえば、「繋がらない」というエラーは、攻撃者にとっても「侵入できない」という最強の壁だ。
エンジニア諸君、便利なだけの環境は、攻撃者にとっても便利な環境だということを忘れるな。今日から、君たちのVPCを見直してほしい。特定のSG ID以外からの通信はすべて DENY されているか? ログには拒否されたパケットが記録されているか?
セキュリティは「設定して終わり」じゃない。「監視して、絞り込んで、育てる」ものだ。明日からの運用で、ぜひこの意識を取り入れてくれ。期待している。
コメント