プロセスの「親」を疑え:Volatility 3で見抜く隠蔽工作と、そもそも侵入を許さない要塞の作り方
現場でインシデント対応をしていると、侵入した攻撃者が最も好む「隠れ蓑」に気づかされます。それがプロセスツリーの偽装(Parent PID Spoofing)です。
正規のシステムプロセスである services.exe や explorer.exe の配下に、見慣れない悪意あるプロセスをぶら下げる。あるいは、プロセスIDを詐称して「さもシステムの一部であるかのように」振る舞う。これらは、EDRの検知をすり抜けるための古典的かつ極めて有効な手法です。
今日は、Volatility 3を使ってこの「死角」を暴く方法と、そもそもそんな隙を与えないための防御術を叩き込みます。
—
1. Volatility 3で「不自然な親子関係」を炙り出す
メモリフォレンジックの世界では、プロセスリストを眺めるだけでは不十分です。攻撃者は PPID(親プロセスID)を書き換えることで、解析者の目を欺こうとします。
階層構造の可視化
Volatility 3には windows.pstree という非常に優秀なプラグインがあります。これを使うと、プロセスの親子関係がツリー形式で出力されます。
# メモリイメージからプロセスツリーを抽出
python3 vol.py -f memory.dmp windows.pstree
ここで見るべきは、「不自然な親」です。
例えば、Webサーバーのバックエンドプロセス(php-fpm や python)が、本来の親である master プロセスではなく、services.exe や winlogon.exe の配下に突然出現していたら、それはインジェクションの兆候です。
PPID不整合の特定
より高度な隠蔽に対し、windows.pslist と windows.psscan を比較します。
pslist: Windowsが管理するプロセスリスト(APIレベルで改ざんされやすい)psscan: メモリ内の構造体を直接スキャン(隠蔽されたプロセスを見つけやすい)
この2つの結果に乖離がある場合、攻撃者はDKOM(Direct Kernel Object Manipulation)等を用いて、タスクマネージャー等の標準ツールから自身の存在を消し去っています。
—
2. そもそも「侵入」を許さない:セキュアな設計の鉄則
フォレンジックはあくまで「起きてしまった後」の作業です。我々エンジニアの真の仕事は、メモリを汚染させないこと、つまりアプリケーション層でコマンドの実行を物理的に防ぐことにあります。
攻撃者がプロセス生成を行う際、最も狙うのが「OSコマンドインジェクション」です。これを防ぐための、現場で使える「最強の防御設定」を伝授します。
PHP/Laravelでの安全なコマンド実行
exec() や system() をむやみに使うのは自殺行為です。どうしてもOSコマンドが必要な場合は、引数をエスケープし、実行環境を隔離します。
// 安全なコマンド実行のサンプル
public function executeSafeCommand($userInput) {
// 1. 入力を厳格にバリデーション(ホワイトリスト方式)
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $userInput)) {
throw new \InvalidArgumentException("不正な入力です。");
}
// 2. escapeshellarg で引数を完全に無害化
$safeArg = escapeshellarg($userInput);
// 3. 実行するコマンドをフルパスで指定(パスジャック防止)
$command = "/usr/bin/git " . $safeArg;
$output = [];
$returnCode = 0;
exec($command, $output, $returnCode);
return $output;
}
—
3. インフラレベルでの多層防御(Nginx + IAM)
アプリケーションの脆弱性は常にゼロにはできません。だからこそ、OSレベルでプロセス生成を制限する「二重の鍵」が必要です。
NginxでのHTTPヘッダー強化
X-Content-Type-Options: nosniff などを設定し、ブラウザ経由での不正な実行を防ぎます。
# /etc/nginx/conf.d/security.conf
server {
# MIMEタイプスニッフィングを防止
add_header X-Content-Type-Options nosniff;
# クリックジャッキング対策
add_header X-Frame-Options "SAMEORIGIN";
# XSS対策
add_header X-XSS-Protection "1; mode=block";
}
AWS IAMでの権限最小化
もしWebサーバーがAWS EC2上で動いているなら、そのインスタンスプロファイルには「システムコマンドを実行する権限」を与えてはなりません。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ssm:SendCommand",
"ec2:RunInstances"
],
"Resource": "*"
}
]
}
*※これは一例ですが、不要なSSM(Systems Manager)の権限を削るだけで、攻撃者はシェルを取っても横展開(Lateral Movement)が大幅に困難になります。*
—
最後に:プロフェッショナルとしての心構え
「メモリを解析すれば何でもわかる」と過信しないでください。真のフォレンジックの達人は、「解析しなくても済むような堅牢なインフラを構築した上で、万が一の際に隠蔽の痕跡を逃さない洞察力」を持っています。
プロセスツリーが不自然に枝分かれしているのを見つけたら、それはあなたの設計したシステムが悲鳴を上げている証拠です。その悲鳴を聞き逃さず、コードの1行1行からセキュリティを担保していく。それが、我々エンジニアに求められる矜持です。
何か怪しい挙動を見つけたら、すぐにメモリをダンプし、pstree を叩いてください。答えは必ずそこにあります。
コメント