おい、ちょっと手を止めてこっちを向いてくれ。
先日、とあるクライアントのインフラ監査に入ったんだが、笑えない事実を目の当たりにした。本番環境の踏み台サーバー(踏み台ですらない、データベースに直結した管理用EC2インスタンスだ)のセキュリティグループが、見事に 0.0.0.0/0 からの TCP/22 (SSH) と TCP/3389 (RDP) を全開放していたんだよ。「急ぎで構築したから」「テスト用の一時的な設定のつもりだった」――毎回お決まりの言い訳だが、攻撃者からすれば、そんな背景は知ったこっちゃない。
インターネットに接続された瞬間から、世界中のボットネットやスクリプトキディの自動スキャナーが、その剥き出しのポートを叩き続けている。今回は、この「セキュリティグループの不備」がどれほど致命的な攻撃対象領域(Attack Surface)の拡大を招くのか、そしてそれをどうやって根絶やしにするのか、現場のリアルな知見を交えて徹底的に解説しよう。
—
1. 攻撃者の視点:なぜ 0.0.0.0/0 のポート開放が即死に繋がるのか
レッドチームの視点から言えば、0.0.0.0/0 からの SSH/RDP 開放は「鍵を差したまま放置された金庫」に等しい。ポートスキャナー(NmapやMasscanなど)を使えば、地球上のどこからでも数秒で該当ポートの存在が暴かれる。
ブルートフォースとクレデンシャルスタッフィングの現実
ポートが開いていれば、次に行われるのは機械的な辞書攻撃(ブルートフォース)だ。
root, ubuntu, ec2-user, administrator といったデフォルトユーザー名に対し、数百万件のパスワードリストが秒速で流し込まれる。パスワード認証が有効になっていれば、どれだけ複雑なパスワードを設定していても、確率論的にいつかは突破されるか、あるいはサービス拒否(DoS)によってリソースが枯渇する。
さらに最悪なのは、キーペアやパスワードが過去のインシデントやGitHubへのうっかりコミットで流出していた場合だ。認証が通った瞬間、彼らは内部ネットワークへの侵入(Lateral Movement)の足がかりを手に入れ、重要データの窃取やランサムウェアの展開へと移行する。
—
2. 攻撃シミュレーション(PoCの概念)
実務の現場で、これがどれほど簡単に自動化されているかを知るために、Pythonを用いた簡易的なポート・バナーチェックの概念コードを見てみよう。攻撃者はこのようなスクリプトでターゲットの不備を検出し、自動攻撃モジュールへ引き渡している。
import socket
import sys
def check_exposed_port(target_ip, port):
"""
指定されたIPとポートへの接続を試み、セキュリティグループの不備(開放状態)を検知する
"""
try:
# ソケットを作成して接続タイムアウトを2秒に設定
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2.0)
result = s.connect_ex((target_ip, port))
if result == 0:
print(f"[!] 警告: ターゲット {target_ip}:{port} が外部に露出しています!")
# バナー情報の取得を試みる
try:
banner = s.recv(1024).decode('utf-8', errors='ignore').strip()
print(f" [+] 取得したバナー情報: {banner}")
except:
print(" [-] バナー情報の取得には失敗しました(接続のみ確立)。")
else:
print(f"[-] ターゲット {target_ip}:{port} は保護されています(または閉じています)。")
except socket.error as e:
print(f"[ERROR] 通信エラーが発生しました: {e}")
finally:
s.close()
if __name__ == "__main__":
# 実務テスト時は必ず許可された環境のIPを指定すること
target = "192.0.2.1" # 例示用のダミーIP
target_port = 22
print(f"[*] スキャン開始: {target}:{target_port}")
check_exposed_port(target, target_port)
このような露出を人力で見つけるのは、広大なクラウド環境では不可能に近い。だからこそ、インフラストラクチャー・アズ・コード(IaC)と自動監査の仕組みが必要になる。
—
3. 対策:インフラコード(IaC)による自動制限とセキュリティ担保
「手動でマネジメントコンソールをポチポチ設定する」という文化は今すぐ捨ててくれ。ヒューマンエラーの温床でしかない。セキュリティグループは必ず Terraform や AWS CDK などの IaC でコード化し、バージョン管理とレビューを通すべきだ。
以下に、AWS (Terraform) を用いて、SSH/RDPの 0.0.0.0/0 を完全に排除し、信頼できる特定のCIDR(社内IPなど)のみに限定するセキュアな設定サンプルを示す。
Terraform 実装サンプル
# セキュリティグループの定義
resource "aws_security_group" "secure_bastion_sg" {
name = "secure-bastion-sg"
description = "管理用の踏み台サーバー向けセキュアなセキュリティグループ"
vpc_id = var.target_vpc_id
# 【重要】インバウンドルール(外から中への通信)
# 以前はここに 0.0.0.0/0 からの 22番ポート許可を書いていたはずだ。それを絶対に排除する。
ingress {
description = "社内ネットワーク(VPN等)からのSSH接続のみを許可"
from_port = 22
to_port = 22
protocol = "tcp"
# 0.0.0.0/0 ではなく、必ず自社の固定グローバルIPやVPNのCIDRを指定する
cidr_blocks = ["203.0.113.50/32"]
}
ingress {
description = "社内ネットワークからのRDP接続のみを許可(Windowsの場合)"
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = ["203.0.113.50/32"]
}
# アウトバウンドルール(中から外への通信)
# 原則として必要最小限に絞るが、パッケージアップデート等のためHTTPSを許可する場合の例
egress {
description = "外部へのセキュアな通信(HTTPS)を許可"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "SecureBastionSG"
Environment = "Production"
ManagedBy = "Terraform"
}
}
—
4. CI/CDパイプラインでの自動監査(Policy as Code)
コードを書くだけでは不十分だ。開発者がうっかり cidr_blocks = ["0.0.0.0/0"] をプルリクエストに含めてしまったとき、それを人間の目だけでレビューするのは限界がある。
そこで、Checkov や Tfsec といった Policy as Code ツールを CI/CD パイプライン(GitHub Actionsなど)に組み込み、セキュリティグループに 0.0.0.0/0 のインバウンドルールが含まれている場合は、自動的にビルドを落とす仕組みを強制する。
以下は、GitHub Actions で Terraform の静的セキュリティ解析を行うワークフローのサンプルだ。
GitHub Actions 設定ファイル (.github/workflows/security-audit.yml)
name: Infrastructure Security Audit
on:
pull_request:
branches:
- main
- master
jobs:
tfsec:
name: Tfsec Security Scanner
runs-on: ubuntu-latest
steps:
# リポジトリのコードをチェックアウト
- name: Checkout Code
uses: actions/checkout@v4
# tfsecの実行(AWS等のセキュリティアンチパターンを検出)
- name: Run tfsec
uses: aquasecurity/tfsec-action@v1.0.3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# 警告レベル以上の検出で強制的にエラー終了させる
hard_fail: true
この設定を入れておけば、万が一誰かが 0.0.0.0/0 を書いたコードをプッシュしても、CIの段階で検知され、マージされることが物理的に不可能になる。これこそが、現場のインフラエンジニアが目指すべき「仕組みで殴るセキュリティ」だ。
—
チーフエンジニアからのまとめ
セキュリティグループの不備は、高度なゼロデイ攻撃なんかじゃない。極めて原始的で、かつ最も多くの企業を沈めてきた「凡ミス」の延長線上にある。
1. 0.0.0.0/0 からの SSH/RDP は絶対に許可しない。(どうしても必要な場合は AWS Systems Manager Session Manager などの踏み台レスなアクセス手段を導入しろ)
2. インフラはすべて IaC でコード化し、レビューを通す。
3. CI/CD パイプラインでセキュリティスキャンを義務化し、人間のうっかりをシステムで防ぐ。
この3つを徹底するだけで、君たちのシステムの攻撃対象領域は劇的に縮小する。明日から自分の管理しているクラウド環境のセキュリティグループを一度すべて棚卸ししてくれ。頼んだぞ。
コメント