utsuroi command injection labs知識ベース 01 / 01
OS Command Injection · Knowledge Base
01

OS Command Injection の基礎

When user input ends up in a shell command

Web アプリが裏側で OS コマンド(pingconverttar 等)を実行する場面で、ユーザ入力をそのままコマンド文字列に組み込むと、シェルのメタ文字を使って任意コマンド実行に至ります。

1. OS Command Injection とは #what-is

// PHP - 商品在庫サーバへの ping 確認機能
$host = $_GET['host'];
exec("ping -c 1 $host", $output);
return implode("\n", $output);

意図は ping -c 1 supplier.example。攻撃者が ?host=supplier.example;cat /etc/passwd を送ると、シェルは ; でコマンドを区切って cat /etc/passwd も実行する。

2. シェルのメタ文字 #shell-meta

3. Blind Command Injection #blind-cmdi

コマンドの実行結果がレスポンスに含まれない場合でも、攻撃可能:

4. 正しい防御 #defense

  1. そもそもシェルを呼ばない — 言語の標準ライブラリで代替できないか検討。例:ファイル操作、HTTP リクエスト、画像変換は全て専用ライブラリがある
  2. シェルを介さない exec APIexecve 系(引数を配列で渡す)。シェルメタ文字が解釈されない
  3. ホワイトリスト検証 — 入力が想定形式(英数字+ドット等)に厳密に一致するかチェック
  4. シェルメタ文字の拒否;|&`$() 等を含む入力を拒否(ブラックリストよりホワイトリストの方が安全だが、補助としては有効)
// 危険:シェル経由の exec、文字列連結
exec("ping -c 1 $host");
// 安全:execve 系、引数を配列で
$descriptors = [];
proc_open(['ping', '-c', '1', $host], $descriptors, $pipes);

// Python
subprocess.run(['ping', '-c', '1', host])  # shell=False (デフォルト)

// Node.js
const { execFile } = require('child_process');
execFile('ping', ['-c', '1', host]);  // execFile はシェルを介さない