【入門編】 コンテナランタイムのメモリダンプ取得手法(runc/containerd) – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!インシデントレスポンスやデジタルフォレンジックの世界へようこそ。
突然ですが、皆さんは「コンテナ技術(DockerやKubernetesなど)」を普段の開発やインフラ管理で使っていらっしゃいますよね。アプリケーションのパッケージングが簡単で、どこでも同じ環境が動くなんて、本当に魔法のような技術です。

でも、ちょっと待ってください。
「コンテナの中身は完全に孤立しているから、ホストOS(大元のパソコン)からは見えないし安全だよね」と思っていませんか?

実はこれ、セキュリティの現場では「危うい思い込み」の一つなんです。
今回は、コンテナランタイム(runcやcontainerd)の裏側で動いているプロセスのメモリを、ホストOS側からどうやって覗き見るのか(メモリダンプの取得)、そしてそれがなぜインシデント調査において重要なのかを、身近な例えを交えながら一歩ずつ優しく紐解いていきましょう!

—

1. 家の鍵と「合鍵」の例えで知る、コンテナの仕組み

コンテナのセキュリティを考えるときによく使われるのが「マンションの部屋」の例えです。

  • ホストOS = マンションの建物全体
  • コンテナ = 各住戸(部屋)

コンテナ技術は、各部屋の住人が勝手に行き来できないように、壁や鍵(名前空間やCgroupsというLinuxの機能)でしっかり区切られていますよね。「自分の部屋の中(コンテナ内)で何をやっているかは、管理人(ホストOS)であっても簡単には覗き見られない」……そう思いたくなります。

しかし、セキュリティインシデント(例えば、コンテナ内で動いているWebアプリが乗っ取られた!)が起きたとき、私たちはどうやって犯人の痕跡を探せばいいでしょうか?
部屋のドアが内側から頑丈に鍵をかけられていても、マンションのオーナー(ホストOSの管理者・フォレンジックアナリスト)であれば、マスターキーを使って合法的かつ強制的に部屋の中を点検する権限を持っています。

メモリフォレンジックの世界でも同じです。コンテナという「部屋」の壁を越えて、中で今まさに何が起きているのか、メモリ(RAM)という頭の中を覗き込む。それが今回お話しする「コンテナランタイムのメモリダンプ取得」なんです。

—

2. なぜコンテナのメモリを覗く必要があるの?

コンテナ内で怪しい動き(マルウェアの実行や不正アクセスの痕跡)があったとき、真っ先にやりたくなるのは「そのコンテナを停止して削除すること」かもしれません。

ちょっと待ってください!それ、一番やっちゃいけない「証拠隠滅」かもしれませんよ。
コンテナの中身は基本的に「使い捨て(エフェメラル)」に作られているため、コンテナを止めてしまうと、犯人が使った悪意あるプログラムや、メモリ上に展開されていた機密情報(パスワードや暗号化キーなど)がすべて消え去ってしまいます。

だからこそ、「コンテナが動いているまさにその瞬間」に、脳ミソのデータをごっそり抜き取る(メモリダンプする)必要があるのです。

—

3. 実践!ホストOSからコンテナのメモリをダンプする手法

それでは、実際にインシデントレスポンスの現場で使われる代表的な手法を見ていきましょう。今回は、KubernetesやDockerの裏方で実際にコンテナを動かしているcontainerdとruncをターゲットにします。

手法A: gcore を使った一番シンプルなアプローチ

Linuxには、動いているプロセスを一時停止させずに(あるいは一瞬止めて)そのメモリ内容をファイルに書き出す gcore という便利なコマンドがあります。

コンテナは、ホストOSから見ると「ただの独立した一つのプロセス」として見えています。そのため、ホストOS側からコンテナのメインプロセスのID(PID)さえ突き止めれば、gcoreでそのままメモリを吸い出すことができるんです。

手順の流れはこうです。
1. ホストOS側で、ターゲットのコンテナのプロセスID(PID)を見つける。
2. gcoreコマンドを使ってメモリをファイルにダンプする。

実際に手を動かすときのコマンド例を見てみましょう。

# 1. まず、動いているコンテナのプロセスID(ホストOS基準)を特定します
# ここでは例として "my-web-container" という名前のコンテナを探します
CONTAINER_PID=$(crictl inspect --output json <コンテナID> | jq .info.pid)
# ※ Dockerの場合は docker inspect --format '{{.State.Pid}}' <コンテナ名> で取得できます

echo "ターゲットのプロセスIDは ${CONTAINER_PID} です"

# 2. 取得したPIDを指定して、メモリダンプ(coreファイル)を生成します
# 注意:このコマンドを実行すると、一時的に対象プロセスが停止することがあります
gcore -o /tmp/container_memory_dump ${CONTAINER_PID}

echo "メモリダンプの取得が完了しました! /tmp/container_memory_dump.${CONTAINER_PID} を確認してください。"

手法B: CRIU(Checkpoint/Restore In Userspace)を活用する高度なアプローチ

もっとガッツリ、メモリだけでなくプロセスのレジスタ情報やネットワークの状態まで丸ごと保存したい!というときに使われるのが CRIU という技術です。

最近のコンテナランタイム(containerd や Podman など)には、コンテナの状態をそのままディスクに保存(チェックポイント)する機能が標準で組み込まれているものがあります。

# containerdの管理ツールである ctr を使って、コンテナの状態をチェックポイント(保存)する例
# ※実行には適切な権限と設定が必要です
ctr -n k8s.io tasks checkpoint --leave-running my-container-id /tmp/checkpoint-dir

echo "コンテナの状態が /tmp/checkpoint-dir にスナップショットとして保存されました。"

この方法の素晴らしいところは、コンテナを無理やり殺さずに、その瞬間の「完全なスナップショット」を安全に取り出せる点です。フォレンジック調査において、これほど頼もしい味方はいませんよね。

—

4. 現場からのワンポイントアドバイス:注意すべき「罠」

ここまで聞くと、「なんだ、意外と簡単にメモリが取れるんだな!」と思われるかもしれませんが、現場ではいくつかの「落とし穴」があります。

1. メモリ食い虫への配慮
コンテナのメモリが数GB〜数十GBある場合、gcoreでダンプファイルを作ると、ホストOS側のディスク容量が一瞬で埋まります。「ディスクが一杯になってホストOSがクラッシュした!」なんてことにならないよう、十分な空き容量を確保してから実行してくださいね。
2. パフォーマンスへの影響
本番環境で稼働中のコンテナに対してメモリダンプを取得すると、一時的にアプリケーションの応答が遅くなったり、タイムアウトが発生したりすることがあります。調査の緊急性と、サービスへの影響度(トレードオフ)を常に天秤にかける心を忘れないようにしましょう。

—

5. 一歩ずつ、確実なセキュリティ対策を

今回は、少しマニアックで現場感あふれる「コンテナランタイムのメモリダンプ取得手法」について解説しました。

「コンテナの中は安全」という思い込みを捨て、万が一のインシデントが発生した際には、ホストOSの管理者としてどのように中身を覗き見ればいいのか。その引き出しを一つ持っているだけで、セキュリティインシデントに直面したときの慌て方が全く変わってきます。

最初は難しい用語や黒い画面の操作に戸惑うかもしれませんが、大丈夫です。こうして一つずつ仕組みを理解していけば、どんな巧妙なサイバー攻撃にも冷静に立ち向かえる頼もしいエンジニアになれますよ。

それでは、また次回のセキュリティ解説でお会いしましょう!安全なインフラライフを!

コメント

タイトルとURLをコピーしました