はじめに
PHPで外部コマンドを呼び出すとき、ユーザ入力をそのまま渡してしまうと コマンドインジェクション脆弱性 の原因になります。この対策として登場するのが escapeshellcmd()
と escapeshellarg()
。しかしこの2つの役割を混同してしまうと、試験や実務で誤解を招きやすいポイントです。
本記事では、両者の違いと正しい使い分けを整理します。
目次
escapeshellcmd() vs escapeshellarg()
関数名:escapeshellcmd(string $command)
目的 | 動作 | 使用する場面 | 安全性 |
---|---|---|---|
コマンド全体の安全化 | コマンド文字列に含まれる危険文字の前にバックスラッシュを付加。 ' と " は対になっていない場合のみエスケープ。 | exec() や system() に コマンド全体を渡す とき | 不完全(引数が分離されると危険) |
サンプル入力
"cat /etc/passwd; rm -rf /"
実際の出力
cat /etc/passwd\; rm -rf /
関数名:escapeshellarg(string $arg)
目的 | 動作 | 使用する場面 | 安全性 |
---|---|---|---|
引数専用の安全化 | 引数全体を ' で囲み、内部の ' は '\'' に変換。 | ユーザ入力を引数に使うとき | 完全(一つの引数として渡される) |
サンプル入力
"/etc/passwd; rm -rf /"
実際の出力
'/etc/passwd; rm -rf /'
実例コード
$user_input = '/etc/passwd; rm -rf /';
// ❌ escapeshellcmd のみ
$cmd = "cat " . escapeshellcmd($user_input);
echo $cmd . PHP_EOL;
// => cat /etc/passwd\; rm -rf /
// → /etc/passwd の後に rm 実行の危険あり
// ✅ escapeshellarg を使用
$cmd = "cat " . escapeshellarg($user_input);
echo $cmd . PHP_EOL;
// => cat '/etc/passwd; rm -rf /'
// → 引数全体が一つにまとまるため安全
試験での押さえどころ
escapeshellcmd()
→ コマンド全体向け(万能ではない)escapeshellarg()
→ ユーザ入力(引数)を安全に渡すため必須- 「escapeshellcmd()で脆弱性を完全に防げる」と断言する記述は 誤り
👉 この違いをしっかり覚えておけば、試験問題で迷わず回答できます。
まとめ
- コマンドインジェクション対策は escapeshellarg() が基本
- escapeshellcmd() は補助的な役割であり「完全防御ではない」
- 試験問題はこの「誤解しやすいポイント」を狙ってくるので要注意!