こんにちは!セキュリティチームで日々インシデントの調査や解析をしているアナリストです。
「コンテナ」という言葉、最近の開発現場ではすっかりお馴染みになりましたよね。「サーバーの環境構築がすぐできて便利!」と、DockerやKubernetesなどを日常的に使っている方も多いと思います。
でも、ふとこんな不安が頭をよぎったことはありませんか?
「もし、このコンテナの中でこっそり悪いことをされたら、どうやって証拠を見つければいいんだろう?」と。
今回は、コンテナという特殊な世界で使われる「メモリ(記憶の断片)」を覗き見するための必須ツール、Volatility 3(ボラティリティ 3)を使った「プロファイル(目録)の作り方」について、一歩ずつ優しく紐解いていきたいと思います。難しい専門用語も、身近な例えに置き換えていくので安心してくださいね!
—
1. コンテナのメモリ解析って、例えるとどんな感じ?
まずは、コンテナの仕組みと今回のテーマを身近な例えで考えてみましょう。
皆さんの家を想像してみてください。
昔ながらの一軒家(通常の物理サーバー)なら、玄関の鍵も窓の鍵も、全部あなた自身で管理していますよね。警察(フォレンジック調査員)がやってきても、家全体の構造が分かりやすいので捜査がスムーズです。
では、「マンションのひと部屋(コンテナ)」はどうでしょう?
コンテナは、大きなマンション(ホストOS)の建物構造をみんなで共有しながら、部屋の中だけ自分好みにリフォームして暮らしているような状態です。
ここで、もしあなたのお部屋の中で「コソ泥(サイバー攻撃者)」が暴れたとします。警察がやってきて「部屋の中の足跡や指紋(メモリデータ)を集めさせてください!」と言ったとき、警察官はこう言うんです。
「このマンション、部屋ごとに壁の厚さや鍵の構造(カーネルのシンボル)が少しずつ違うから、この部屋専用の『間取り図と鍵の仕組みの解説書(シンボルテーブル)』がないと、中を正確に捜査できないよ!」と。
そう、コンテナのメモリを解析するには、そのコンテナが動いている「カーネル(OSの心臓部)」の正確な設計図(シンボル)を、解析ツールであるVolatility 3に教えてあげる必要があるのです。これが「プロファイルの作成」という作業になります。
—
2. なぜVolatility 3でコンテナ解析につまずくのか?
従来の「Volatility 2」という古いバージョンでは、あらかじめ用意された大量のプロファイルから選ぶだけで動くこともありました。しかし、今の主流である「Volatility 3」は、よりスマートに進化する一方で、ちょっとした「融通のきかなさ」があります。
コンテナの中身を調査しようと、いざメモリイメージ(memdump.raw など)をVolatility 3に放り込んでみても、次のようなエラーが出て途方に暮れてしまう新米エンジニアが後を絶ちません。
> 「あれ? カーネルのシンボルが見つからないって怒られちゃった……どうしよう?」
コンテナは軽量化のためにOSの機能を削ぎ落としていたり、ホストとは違う特殊なカーネルバージョンを使っていたりします。だからこそ、そのコンテナ専用の「設計図(JSON形式のシンボルテーブル)」を自分で手作りしてあげる必要があるんですね。
—
3. 実践!コンテナ用シンボルテーブルの作り方
それでは、実際にコンテナのメモリ解析に必要な「設計図」を作る手順をみていきましょう。
一歩ずつ進めれば決して難しくありませんので、一緒に手を動かしていきましょう!
ステップ1:必要な道具(Dwarf2Json)の準備
Volatility 3でカスタムのシンボルテーブルを作るためには、カーネルのデバッグ情報(Dwarf形式)を、Volatilityが読めるJSON形式に翻訳するツール dwarf2json を使います。
Go言語の環境が整っていれば、コマンド一発でインストールできます。
# 翻訳ツールである dwarf2json をインストールします
go install github.com/volatilityfoundation/dwarf2json@latest
# インストールされた場所を確認しておきましょう
which dwarf2json
ステップ2:コンテナ(またはホスト)のカーネルから設計図を抽出する
次に、解析対象のコンテナが使っているカーネルのファイル(通常は vmlinux やそれに準ずるデバッグ情報が含まれるファイル)を用意します。
コンテナ環境によっては、ホスト側のカーネルイメージや、デバッグシンボルパッケージ(kernel-debuginfo など)を別途インストールして取得する必要があります。
用意ができたら、dwarf2json を使ってVolatility 3用のシンボルテーブル(JSONファイル)に変換しましょう。
# カーネルのデバッグ情報から、Volatility 3用のシンボルテーブル(JSON)を生成する
# 出力されたファイルは、Volatility 3の symbols フォルダに配置します
dwarf2json linux --elf /path/to/vmlinux > linux-container-profile.json
※ここで生成された linux-container-profile.json が、まさに「このコンテナ専用の鍵の仕組みの解説書」になります。
ステップ3:Volatility 3に読み込ませて解析を実行する
さあ、いよいよ準備完了です!作成したシンボルテーブルを指定して、コンテナのメモリイメージ(例: container_mem.raw)を解析してみましょう。
Volatility 3を実行する際、カスタムのシンボルファイルを置いたパスを指定するか、シンボルディレクトリにファイルを格納します。
# Volatility 3を実行し、コンテナ内で動いていたプロセス一覧を表示してみる
# -s オプション等でシンボルファイルのパスを明示的に指定します
python3 vol.py -s /path/to/symbols/ -f container_mem.raw linux.pslist
もしここで、コンテナ特有のプロセス(例えば、特定の名前空間に閉じ込められたプロセスたち)がきれいにリストアップされたなら大成功です!「やったね!」と自分を褒めてあげてください。
—
4. 現場のプロからのアドバイス:見落としがちな落とし穴
最後に、実際のインシデントレスポンスの現場で私たちが直面する「ちょっとした罠」についてお伝えしておきます。
1. カーネルバージョンの完全一致が命
「ちょっとくらいバージョンが違っても動くでしょ?」という甘い考えは、メモリフォレンジックにおいては通用しません。コンテナがビルドされた瞬間のカーネルソースやヘッダーファイルと、生成したシンボルテーブルのバージョンが1バイト単位で一致している必要があります。微小なズレが、解析結果をすべてデタラメにしてしまう原因になります。
2. コンテナの「namespace(名前空間)」を意識する
コンテナはプロセスを隔离(アイソレート)しています。Volatilityでプロセスリスト(linux.pslist)を見るとき、ホストから見たプロセスと、コンテナの中から見たプロセスがどう紐づいているかを意識することが、侵入経路を特定する大きな手がかりになります。
—
まとめ
いかがでしたでしょうか?
「コンテナのメモリ解析」や「Volatility 3のシンボルテーブル作成」と聞くと、なんだか呪文のように難しく感じられたかもしれません。でも、「マンションの部屋(コンテナ)ごとに違う鍵の構造(シンボル)を、専用の解説書(JSON)で教えてあげる作業なんだ」と捉えれば、少し親しみを持っていただけたのではないでしょうか。
セキュリティの技術は、地道なパズルの組み合わせです。焦らず、一歩ずつ、自分の手で環境を動かしながらマスターしていきましょう。
あなたのインシデントレスポンスの旅が、実り多いものになるよう応援しています!それではまた次の記事でお会いしましょう!
コメント