なぜ「メモリ」が最後の聖域なのか:LSASS攻略と現代の防衛戦略
現場でインシデントレスポンスを指揮していると、多くのエンジニアが「パスワードを複雑にしたから安全だ」「多要素認証(MFA)を入れたから大丈夫」と過信している場面に遭遇します。しかし、攻撃者はそんな「お作法」など鼻で笑って、もっと根本的な場所を狙います。それが、Windowsのメモリ上にある lsass.exe です。
今回は、なぜ攻撃者がメモリを執拗に狙うのか、そしてそれに対して我々がどう「ゼロトラスト」を実装すべきか、技術的な深淵を覗いてみましょう。
—
1. 攻撃者の視点:なぜ LSASS なのか?
Local Security Authority Subsystem Service、通称 LSASS は、Windowsにおいて認証情報の管理を一手に引き受けるプロセスです。ここにログイン中のユーザーの平文パスワード、NTLMハッシュ、そしてKerberosチケットがメモリ上に保持されます。
攻撃者は、システムに侵入した後、権限昇格(Privilege Escalation)を経てこのプロセスにアクセスし、Mimikatz のようなツールを使ってメモリをダンプします。これは単なる「パスワードの盗難」を超え、組織内での「なりすまし」や「ドメインコントローラーへの横展開」を容易にする、いわばマスターキーの強奪です。
攻撃の仕組み(概念的なPoC)
攻撃者は OpenProcess APIを使用してLSASSプロセスへのハンドルを取得し、そのメモリ領域を読み取ります。防御が甘い環境であれば、以下のコマンド一行であなたの組織は全滅します。
# 攻撃者が実行する Mimikatz の典型的なプロセスダンプ例
sekurlsa::minidump lsass.dmp
sekurlsa::logonpasswords
この結果、平文パスワードが平然と表示されるわけです。これが、私たちがインシデント現場で一番見たくない光景です。
—
2. 決定的な防衛策:Credential Guard の採用
「メモリをダンプさせない」ことが唯一の正解です。しかし、権限昇格されて SYSTEM 権限を取られたら、ソフトウェアレベルでの防御は限界があります。ここで登場するのが Credential Guard です。
Credential Guard は、仮想化技術(VBS)を利用し、認証情報をOSカーネルからも隔離された「隔離された仮想コンテナ」内に格納します。つまり、lsass.exe のメモリをいくらダンプしても、そこには重要な秘密情報は存在しないのです。
設定の勘所:グループポリシーによる強制
インフラ運用者は、以下の設定をドメイン全体に強制適用してください。
1. グループポリシーエディタを開く (gpedit.msc)
2. [コンピューターの構成] > [管理用テンプレート] > [システム] > [Device Guard] を開く
3. [仮想化ベースのセキュリティを有効にする] を 有効 にする
4. [資格情報のガードの構成] を 有効 にし、「UEFI ロック付きの有効化」を選択する
—
3. アプリケーション層からの防御:認証の「オフロード」
インフラ側で防御を固めるのは当然ですが、我々エンジニアが開発するWebアプリケーションも、ユーザーの認証情報を極力ローカルに持たせないアーキテクチャにする必要があります。
特に、サーバーサイドで Kerberos チケットや生パスワードをキャッシュするような実装は、メモリフォレンジックの標的になることを意味します。以下のコード例は、認証情報をメモリに保持せず、セキュアなトークン管理を行うための設計指針です。
セキュアなトークン管理(Python/FastAPIの例)
Redis などの外部インメモリDBにセッションを逃がし、メモリ上には「セッションID(ランダム文字列)」のみを保持するように設計します。
# セッションデータをメモリに直書きせず、暗号化して外部キャッシュへ
import redis
import secrets
# セッション管理用クライアント
cache = redis.Redis(host='localhost', port=6379, db=0)
def create_user_session(user_id):
# 予測不能なセッションIDを生成
session_id = secrets.token_urlsafe(32)
# 認証情報を直接メモリに置かず、RedisにTTL付きで保存
# 接続先はTLS/SSLで保護すること
cache.setex(f"session:{session_id}", 3600, user_id)
return session_id
フロントエンドでの保護(JavaScript/ブラウザ側)
localStorage へのパスワード保存などは論外です。HttpOnly かつ Secure 属性の付与されたクッキーを使用し、XSS攻撃によるトークン奪取を防ぎます。
// Nginxでのセキュアなヘッダー設定例
// 開発者が確認すべき重要なレスポンスヘッダー
add_header Set-Cookie "session_id=...; HttpOnly; Secure; SameSite=Strict";
add_header Content-Security-Policy "default-src 'self';";
add_header X-Content-Type-Options "nosniff";
—
最後に:フォレンジックの現場からの教訓
メモリフォレンジックの世界では、「完璧な防御」は存在しません。しかし、「攻撃コストを跳ね上げる」ことは可能です。
LSASSを狙う攻撃者は、我々が「どこをサボっているか」を敏感に嗅ぎ取ります。Credential Guardを有効にし、認証情報をメモリから隔離し、アプリケーション層でもセッション情報を適切に管理する。この3段構えを徹底すれば、少なくとも「初歩的なツールで全滅」という最悪のシナリオは防げます。
エンジニアの皆さん、コードを書くとき、サーバーを立てるとき、「もしここに攻撃者が侵入したら、私の書いたコードは情報を差し出してしまうか?」という問いを常に自分に投げかけてください。それが、プロフェッショナルのセキュリティです。
コメント