こんにちは!インシデントレスポンスの現場を渡り歩いているSOCアナリストです。
今回は、最近のシステム開発やインフラ運用で欠かせない「コンテナ環境」における、ちょっとディープで面白いメモリフォレンジックのお話です。
「コンテナの中身を調査したいのに、ホストから覗き見るとPID(プロセスID)の数字が全然噛み合わない……!」
そんなモヤモヤを感じたことはありませんか?
今回は、新人のIT担当者や、セキュリティに初めて触れる開発者の方に向けて、コンテナの「名前空間」という仕組みと、それがメモリ解析にどう影響するのかを、身近な例えを交えながら一歩ずつ優しく紐解いていきたいと思います。ぜひ最後までお付き合いくださいね!
—
1. 家の中に「もう一つの部屋」がある? コンテナと名前空間の仕組み
まずは、コンテナの仕組みを私たちの身の回りの防犯や生活に例えて考えてみましょう。
一戸建ての「家(ホストOS)」の中に、鍵付きの「個室(コンテナ)」をいくつか作ったと想像してください。個室の中に住んでいる人(コンテナ内のプロセス)から見ると、自分の部屋が世界のすべてです。自分の部屋の中では、自分が一番えらい「ID: 1」の主(お父さんやお母さん)だと思い込んでいます。
しかし、家の外(ホストOSの管理人)から家全体を見渡すとどうでしょう?
「あっちの部屋の主は全体の中で『ID: 1052』、こっちの部屋の主は『ID: 2084』だな」と、すべての住人の本当の姿がハッキリと見えていますよね。
この「自分からは小さな世界しか見えないように区切る仕組み」のことを、Linuxの世界では名前空間(Namespace)と呼びます。
- PID名前空間: プロセスIDの番号をコンテナごとに独立させる仕組み
- マウント名前空間: ファイルシステムの見え方をコンテナごとに分ける仕組み
開発者にとっては、アプリが他の環境と混ざらないように隔離してくれて非常に便利なのですが、いざ「不正アクセスがあったから、メモリの中身を調査しよう!」となった時、この仕組みがセキュリティエンジニアの頭を悩ませる大きな壁になるのです。
—
2. メモリフォレンジックの罠:なぜ「見たいプロセス」が見つからないのか?
インシデントレスポンスの現場では、怪しい動きをしているプログラムのメモリ(RAM)をダンプして解析します。
伝統的なメモリ解析ツール(Volatile Memory Forensicツールなど)は、基本的に「ホストOSの視点」でメモリ全体を俯瞰します。ここで問題が発生します。
1. ホストOSのツールで「PID 1のプロセス」のメモリを覗こうとする。
2. しかし、それはコンテナの中にあるメインプロセスではなく、ホスト側の全然関係ないシステムプロセスを指しているかもしれない。
3. 逆に、コンテナの中で動いている悪意あるプログラム(例: PID 42)は、ホストから見ると別の大きな数字(例: PID 3450)として存在している。
結果として、「どのオフセット(メモリ上の位置)を指して解析すればいいのか分からない!」というパニックに陥ってしまいます。まるで、住所の「◯丁目◯番地」を聞いているのに、部屋番号を無視して建物全体の名前だけで部屋を探そうとするようなものです。
—
3. ホストからコンテナのメモリを正しくマッピングするための考え方
では、このバラバラになった「住所」をどうやって正しく結びつければよいのでしょうか?
ここが、今回のテーマのキモである「オフセットの計算と名前空間の紐付け」です。
現場では、以下のような手順でパズルを解いていきます。
1. コンテナのコンテキストを特定する
まずは、調査対象のコンテナがホスト上でどのプロセスとして起動しているのか、そのCgroup(コントロールグループ)や名前空間の識別子(inode番号など)を特定します。
2. PIDの変換テーブル(マッピング)を導き出す
カーネルのデータ構造(nsproxyやpid_namespaceなど)を辿り、「コンテナ内のPID 1」が「ホスト上のPID XXXX」のどこに隠れているのかを割り出します。
3. 物理・仮想アドレスのオフセットを再計算する
コンテナ特有のメモリ空間のベースアドレス(基準点)に、コンテナ内の相対的なオフセットを足し合わせることで、ホストのメモリイメージから正確なデータを切り出します。
言葉だけ聞くと難しそうですが、要は「翻訳機を通して正しい住所に書き直す作業」を行っているだけなんです。
—
4. 実務で役立つ! コンテナのプロセス調査を支援するシェルスクリプト例
実務の現場では、手作業で複雑なカーネル構造体を計算するのは大変ですし、時間が勝負のインシデントレスポンスでは命取りになります。
そこで、ホストOSからコンテナ内のプロセスIDや名前空間のつながりをサクッと確認するための、実用的なスクリプトのアイデアをご紹介します。
以下のサンプルコード(Bashスクリプト)は、ホスト上のプロセスとコンテナ(PID名前空間)の関係性を可視化するためのものです。環境構築やデバッグの際に、ぜひ参考にしてみてください。
#!/bin/bash
# ==============================================================================
# スクリプト名: check_container_namespaces.sh
# 概要: ホストOS上で稼働するプロセスと、対応するPID名前空間の関係をリスト化します。
# 使い方: sudo ./check_container_namespaces.sh
# ==============================================================================
# 実行ユーザーがrootかどうかを確認する(フォレンジック作業には権限が必須です)
if [ "$EUID" -ne 0 ]; then
echo "[-] エラー: このスクリプトはroot権限で実行する必要があります。" >&2
exit 1
fi
echo "[+] ホストおよびコンテナのPID名前空間のマッピング調査を開始します..."
echo "----------------------------------------------------------------------------"
printf "%-8s | %-8s | %-30s | %s\n" "HOST PID" "NS INODE" "COMMAND" "CONTAINER INFO"
echo "----------------------------------------------------------------------------"
# /proc ディレクトリ以下の各プロセスを走査する
for pid_dir in /proc/[0-9]*; do
pid=$(basename "$pid_dir")
# プロセスが存在し、かつPID名前空間のシンボリックリンクが存在するか確認
if [ -e "$pid_dir/ns/pid" ]; then
# PID名前空間のinode番号を取得する(同じ名前空間ならinode番号が一致します)
ns_inode=$(readlink "$pid_dir/ns/pid" | awk -F'[{}]' '{print $2}')
# プロカントの実行コマンド名を取得
if [ -f "$pid_dir/comm" ]; then
comm=$(cat "$pid_dir/comm")
else
comm="N/A"
}
# Docker等のコンテナランタイムに関連する情報があれば簡易的に表示
cgroup_info=$(grep -i "docker" "$pid_dir/cgroup" 2>/dev/null | head -n 1)
if [ -n "$cgroup_info" ]; then
container_tag="Docker Container"
else
container_tag="Host Process"
fi
# 整形して出力
printf "%-8s | %-8s | %-30s | %s\n" "$pid" "$ns_inode" "$comm" "$container_tag"
fi
done
echo "----------------------------------------------------------------------------"
echo "[+] 調査が完了しました。特定の名前空間(NS INODE)に属するPIDを元にメモリ解析を進めてください。"
このコードのポイント
readlink "$pid_dir/ns/pid"を使うことで、そのプロセスがどのPID名前空間に属しているかを「inode番号」という一意のIDで特定しています。- これにより、「どのプロセスとどのプロセスが同じコンテナ(同じ個室)の中にいるのか」を一発で見分けることができます。
—
5. まとめ:一歩ずつ、確実なフォレンジックへ
今回は、コンテナ環境におけるメモリフォレンジックの大きな壁である「名前空間の分離」と「オフセットの重要性」についてお話ししました。
- コンテナは「家の中の個室(名前空間)」のようなもの。
- ホストから見るとプロセスの住所(PID)が書き換わっているため、そのままではメモリ解析の照準がズレてしまう。
- カーネル構造や名前空間の結びつき(inodeなど)を理解し、正しいマッピングを行うことが調査成功の鍵になる。
最初は複雑な用語が多くて圧倒されてしまうかもしれませんが、基礎的な仕組みを一つずつ紐解いていけば、決して越えられない壁ではありません。
日々の開発やインフラ運用の片隅で、「あ、あの時勉強した名前空間の仕組みがここで繋がったな」と感じる瞬間がきっとやってきます。
それでは、安全で快適なセキュリティライフを!また次回の記事でお会いしましょう!
コメント