現場の泥臭い戦い:VPCフローログを「ただの保存用ログ」で終わらせないために
インシデントレスポンスの現場に立つと、常に痛感させられることがある。「ログを取っていること」と「ログが役に立つこと」の間には、深くて暗い谷があるということだ。
多くの現場で、AWSのVPCフローログやAzureのNSGフローログは、S3やBlob Storageに放り込まれ、コンプライアンス要件を満たすためだけの「デジタルな墓標」になっている。だが、一度侵害が発生すれば、その墓標を掘り返して、犯人の足跡を血眼になって探すことになる。
今日は、そんな事後対応で泣かないために、日々の運用でどうやって「異常」を炙り出すか、その実践的なアプローチを共有する。
—
攻撃者の視点:彼らはなぜ「ポートスキャン」を隠さないのか
攻撃者が外部からあなたのクラウド環境を狙うとき、彼らは決して最初から精密な爆弾を投下しない。まずは「偵察」だ。
- ポートスキャン: 未公開の管理画面(
8080や8443)や、誤って開放されたデータベース(3306や5432)を探す。 - データ持ち出し(Exfiltration): 侵害したサーバーから、外部の攻撃者用サーバー(C2サーバー)へ、数ギガバイトのデータを
scpやrsyncで送る。
彼らは「ログに記録されること」を恐れていない。なぜなら、多くの運用チームが「異常な通信量」や「許可されていないポートへのアクセス」をリアルタイムで検知する仕組みを持っていないことを知っているからだ。
—
実践:VPCフローログによる「異常」の検知ロジック
フローログを単に眺めるのではなく、特定の「しきい値」を超えた通信を自動検知するのが定石だ。以下に、Pythonを用いた解析の簡易ロジックを示す。これは、特定のIPからの異常な通信量を検知するための、現場で使えるプロトタイプだ。
Pythonによる異常通信検知の概念コード
import pandas as pd
# フローログを読み込む想定(実際はAthenaやBigQueryから抽出したもの)
# srcaddr: 送信元, dstaddr: 送信先, dstport: 目的地ポート, bytes: データ量
def detect_anomalies(log_data):
df = pd.DataFrame(log_data)
# 1. 未許可のポートへのアクセスを特定
allowed_ports = [80, 443]
suspicious_access = df[~df['dstport'].isin(allowed_ports)]
# 2. 特定の送信元からのデータ転送量がしきい値(例: 100MB)を超えたものを抽出
threshold = 100 * 1024 * 1024
heavy_traffic = df.groupby('srcaddr')['bytes'].sum()
attackers = heavy_traffic[heavy_traffic > threshold]
return suspicious_access, attackers
# 運用メモ: Athenaでクエリを投げ、結果をLambdaでSlack通知する形が最も合理的
—
防御の要:インフラ側での「徹底的な拒否」
解析したログで異常を見つけたところで、対応が遅れれば手遅れだ。そもそも「必要な通信以外は一切通さない」という設計思想(ゼロトラストの基本)をインフラ設定に落とし込む必要がある。
AWS セキュリティグループの「守りの定石」
多くのエンジニアが「取り敢えず全開放(0.0.0.0/0)」の設定で苦しむ。最低限、以下のルールを徹底してほしい。
- アウトバウンドの制限: サーバーがインターネットへ無制限に通信できる状態は、バックドア設置を容易にする。必要なドメイン以外への接続は、NAT GatewayやEgress Only Internet Gatewayで制限すべきだ。
- インバウンドの最小化:
22(SSH) や3389(RDP) は絶対に公開しない。AWS Systems Manager (SSM) Session Manager を使えば、ポートを開けずにセキュアなシェルアクセスが可能だ。
実装例:TerraformによるセキュアなSG設定
# 安全なインバウンド設定例
resource "aws_security_group" "web_server" {
name = "web-server-sg"
description = "許可された通信のみを許可"
# HTTP/HTTPSのみを許可
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"] # VPC内からのアクセスのみ許可
}
# アウトバウンドを厳格に制限(例: APIエンドポイントのみ)
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.5.0/24"] # 特定のサブネットのみに許可
}
}
—
最後に:フォレンジックは日常の延長にある
「インシデントが発生してからログを解析すればいい」というのは、火災報知器が鳴ってから避難経路を探すのと同じくらい危険だ。
1. ログを可視化する: AWSならCloudWatch Logs InsightsやAthenaを使い、ダッシュボードで異常なスパイクがないか毎日確認する。
2. 自動化する: 上記のようなPythonロジックをサーバーレス関数(Lambda/Cloud Functions)に組み込み、怪しい動きがあれば即座に管理者へ通知を飛ばす。
3. 「疑う」習慣: 自分の書いたコードや設計したインフラが「破られる前提」で動く。これが、プロのエンジニアの矜持だ。
セキュリティは、魔法のようなツールを入れることではない。地味なログの積み重ねと、泥臭いルール作り、そして「何かおかしい」という第六感を技術的に裏付ける準備のことなのだ。
君たちが守るシステムは、君たちが思っている以上に狙われている。だが、それ以上に君たちが正しく準備をしていれば、攻撃者は必ず爪痕を残して去らざるを得なくなる。健闘を祈る。
コメント