悪夢を繰り返さないために:SMBプロトコルが抱える「信頼」の代償とラテラルムーブメントの正体
現場でネットワーク機器のログを眺めていると、時折背筋が凍るようなトラフィックに出くわすことがあります。特に、深夜の監視画面に流れる「ポート 445 への異常なアクセス数」は、多くのエンジニアにとってトラウマに近い光景でしょう。
WannaCryが世界を震撼させてから数年が経ちますが、なぜ未だに「SMB(Server Message Block)」を悪用した感染拡大が止まらないのでしょうか?今日は、教科書的な定義を一旦横に置き、現場の泥臭い目線から、SMBがなぜランサムウェアの「高速道路」になってしまうのか、そのメカニズムと防御策を深掘りします。
—
1. SMBは「信頼」という名の脆弱性を運ぶ
SMBは、Windows環境においてファイル共有やプリンタ共有を行うためのプロトコルですが、その本質は「認証されたクライアントを無条件に信頼する」という設計思想にあります。
特に SMBv1 は、その実装の複雑さとレガシーな仕様から、攻撃者にとっては格好の標的です。WannaCryが用いた EternalBlue は、SMBパケット内に細工された特殊なリクエストを送り込み、サーバー側のメモリ破壊を誘発してコードを実行させるという、極めて凶悪な手法でした。
なぜ「ラテラルムーブメント(横展開)」が止まらないのか
感染したPCが内部ネットワーク内で 445 ポートをスキャンし、脆弱な端末を見つけると、即座に「認証をバイパスしたリモートコード実行」を試みます。これが、人の手を介さずに秒単位で社内LANを駆け巡る「ワーム」の正体です。境界防御だけで安心していては、内部に入り込まれた瞬間にゲームセットなのです。
—
2. パケットレベルで見るSMBの挙動
SMBの通信フローは、通常 TCP 445 でセッションを確立(SYN → SYN/ACK → ACK)した直後に、「Negotiate Protocol Request」から始まります。
クライアント -> サーバー: TCP SYN
サーバー -> クライアント: TCP SYN/ACK
クライアント -> サーバー: TCP ACK
[ここでSMBセッション開始]
クライアント -> サーバー: SMB_COM_NEGOTIATE (プロトコルバージョンを交渉)
サーバー -> クライアント: SMB_COM_NEGOTIATE Response (v1, v2, v3のどれを使うか決定)
攻撃者は、この「交渉」フェーズで相手のOSやパッチ状況をプロファイリングします。特に SMBv1 のレスポンスを返すサーバーは、攻撃者から見れば「パッチ未適用の脆弱な標的」という看板を掲げているようなものです。
—
3. 実践:SMBの可視化と防御設定
現場では、「どの端末が 445 ポートを叩いているか」を即座に特定できる体制が不可欠です。まずは、現在ネットワーク内で SMBv1 が動いていないか、PowerShellで確認しましょう。
PowerShellでのSMBv1有効状況確認
# 現在のSMBサーバー構成を確認
Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol
# もし True なら、以下のコマンドで即座に無効化すべきです
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
ネットワーク境界での防御:iptables / nftablesによる制御
Web APIを運用するバックエンド環境であっても、内部ネットワークの通信を放置してはいけません。サーバー間通信でSMBが不要なら、迷わず遮断します。
# 内部からの不正なSMBスキャンをブロックするiptables設定
# 外部公開サーバーから内部ネットワークへの445通信をドロップ
sudo iptables -A INPUT -p tcp --dport 445 -j DROP
sudo iptables -A OUTPUT -p tcp --dport 445 -j DROP
# ログを記録して異常な挙動を検知できるようにする
sudo iptables -A INPUT -p tcp --dport 445 -j LOG --log-prefix "SMB_ATTEMPT: "
—
4. ゼロトラスト的アプローチ:APIエンジニアができること
Web API開発者の皆さんは、「自分たちはSMBなんて使っていないから関係ない」と思っていませんか?しかし、CI/CDパイプラインの共有ストレージや、監視ツールの設定ファイル配布など、意外なところで SMB がバックグラウンドで動いていることがあります。
Pythonによる「ポート開通」の簡易チェック(自衛用)
ネットワークの疎通確認を行う際、socket モジュールで対象が意図せずSMBを喋っていないか確認するスクリプトを書く癖をつけましょう。
import socket
def check_smb_port(target_ip):
# 445ポートが空いているかチェック
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(2)
result = s.connect_ex((target_ip, 445))
if result == 0:
print(f"[!] 警告: {target_ip} でポート445が開いています。確認してください。")
else:
print(f"[+] {target_ip} は安全です。")
# 監視対象サーバーのリストを走査する
servers = ["192.168.1.10", "192.168.1.11"]
for ip in servers:
check_smb_port(ip)
—
最後に:ネットワークを「性悪説」で設計する
SMBの脆弱性を突いた攻撃を防ぐための最大の秘訣は、「ネットワーク内は安全である」という前提を捨てることです。
1. マイクロセグメンテーション: サーバー間、セグメント間の通信を最小限に絞る(445 は原則全遮断)。
2. プロトコルのモダン化: SMBv1 は過去の遺物です。SMBv3 を使用し、暗号化(SMB Encryption)を強制してください。
3. 可視化の徹底: SIEM等で 445 へのアクセスログを相関分析し、異常なスパイクがあれば自動で隔離(隔離VLANへの移動など)する仕組みを検討してください。
技術は常に進化しますが、悪意あるコードも同様です。プロトコルの裏側にある「なぜその通信が走るのか」という問いを忘れずに、強固なインフラを築いていきましょう。何かあれば、また現場の知見を共有します。健闘を祈ります。
コメント