メモリは嘘をつかない:lsass.exeから認証情報を守るための「現場の知見」
現場のインシデントレスポンスにおいて、攻撃者がドメインコントローラーや重要サーバーへ侵入した際、最初に何をするか知っているか?
彼らはコマンドラインで派手な攻撃をする前に、まず静かに「メモリ」を覗く。ターゲットはWindowsの認証を司る心臓部、lsass.exe(Local Security Authority Subsystem Service)だ。ここには、ログインしたユーザーの平文パスワードやNTLMハッシュ、Kerberosチケットが「どうぞお持ち帰りください」と言わんばかりに並んでいる。
今日は、この「認証情報の抽出」という泥沼にどう立ち向かうか、教科書には載っていない実践的な防衛ラインを解説する。
—
なぜ「lsass.exe」は狙われるのか?
攻撃者が mimikatz を実行する時、彼らは自身の権限を SeDebugPrivilege に昇格させ、lsass.exe のメモリ空間をダンプする。なぜなら、Windowsはシングルサインオンを実現するために、認証情報をメモリ上にキャッシュし続ける必要があるからだ。
一度このプロセスからハッシュやチケットを盗めば、攻撃者はパスワードそのものを知らなくても、そのユーザーになりすましてネットワーク内を自由に横行できる。これが「Pass-the-Hash (PtH)」や「Pass-the-Ticket (PtT)」の正体だ。
—
実践的防御:Credential Guardの導入
「パスワードを複雑にする」といった対策は、メモリ上のハッシュを盗まれた瞬間、何の意味も持たなくなる。我々がまずやるべきは、lsass.exe 自体を隔離することだ。
Windows 10/11およびServer 2016以降であれば、「Credential Guard」を有効にすることが最強の防御になる。これは仮想化技術(VBS)を用いて、認証情報をカーネルの隔離されたメモリ領域に格納し、たとえ SYSTEM 権限を持つ攻撃者であってもメモリダンプから情報を抜き出せないようにするものだ。
設定ファイルの例(グループポリシー:GPO)
ドメイン環境であれば、以下の設定を適用して強制する。
[設定パス]
コンピュータの構成 > 管理用テンプレート > システム > Device Guard > 仮想化ベースのセキュリティを有効にする
[設定値]
- 仮想化ベースのセキュリティの種類:有効 (セキュアブートとDMA保護)
- Credential Guardの構成:有効 (UEFIロックあり)
これを適用すると、lsass.exe のメモリ内から認証情報が「切り離され」、Mimikatzで攻撃しても空っぽのゴミデータしか返ってこなくなる。
—
開発エンジニアができる「もう一つの防衛線」
メモリダンプを防ぐのはインフラ側の仕事だが、アプリケーション開発者も「認証情報をメモリに長時間残さない」という設計思想を持つべきだ。
例えば、PHPやPythonで外部APIを叩く際、環境変数や設定ファイルにベタ書きしたAPIキーを平文で変数に保持し続けていないか?
セキュアなキー管理の実装例(Python)
メモリ上の生存期間を最小化し、必要最低限のスコープで扱うための例だ。
import os
import secrets
def get_sensitive_data():
"""
環境変数から読み込み、処理終了後にメモリから破棄する設計
"""
# メモリ上に長時間キャッシュせず、必要な時だけ呼び出す
api_key = os.getenv("API_SECRET_KEY")
try:
# ここで処理を実行
return perform_secure_transaction(api_key)
finally:
# Pythonのガベージコレクションを待たず、参照を明示的にクリア
# (完全なメモリ消去は言語仕様上難しいが、参照を断つことが重要)
api_key = None
# 補足:環境変数自体もlsass等から流出するリスクがあるため、
# 本番環境では AWS Secrets Manager や HashiCorp Vault を使い、
# メモリ上での滞留時間を極小化するのが正解だ。
—
最後に:SOCアナリストからの忠告
「設定すれば終わり」ではない。攻撃者は常に進化している。昨今のインシデントでは、lsass.exe を直接叩くのではなく、SAM ファイルをオフラインで解析したり、サードパーティ製のセキュリティソフトのドライバを悪用してカーネルメモリを読み取る手口も増えている。
1. EDRの導入と監視: mimikatz.exe というプロセス名だけでなく、lsass.exe に対する不審な OpenProcess 要求(特定のハンドル権限)を検知せよ。
2. 特権の最小化: ローカル管理者権限(Local Admin)を全端末から剥奪せよ。SeDebugPrivilege を持たないユーザーには、攻撃のハードルは格段に上がる。
3. 定期的な再起動: lsass.exe のメモリを定期的にリフレッシュする運用も、古臭いが地味に効く。
エンジニア諸君、メモリは情報の墓場だ。そこに何を残すか、どう守るか。その意識一つで、君たちのシステムは「狙いやすい鴨」から「難攻不落の要塞」へと変わる。日々の運用の中で、常に「もし今、メモリをダンプされたら?」という問いを持ち続けてほしい。
コメント