引数インジェクション
Web アプリケーションが,利用者が指定したファイル名を引数として ls -l コマンドを起動している。OS コマンドインジェクション対策として,シェルを介さない API でコマンド名と引数を別々に渡し,入力値が英数字とハイフンだけから成ることを検証している。ところが,ファイル名として「-aR」を指定すると,ディレクトリ全体を再帰的に一覧表示できてしまった。この問題への対策として,最も適切なものはどれか。
- アシェルを介した起動に戻し,入力値全体を引用符で囲んで一つの引数としてコマンドに渡す。
- イコマンドを,環境変数 PATH に依存しないフルパスで指定して起動する。
- ウ入力値の検証を,「;」「|」「&」などシェルのメタ文字を含む値を拒否する方式に変更する。
- エコマンドの引数の前に「--」を置いてオプションの解釈を終了させるか,入力値の先頭が英数字であることを検証する。
正解と解説を見る
正解 エ
この問題の基礎知識
- OS コマンドインジェクションは,入力値に含まれるシェルのメタ文字が解釈され,意図しないコマンドを実行される脆弱性であり,シェルを介さずにコマンド名と引数を分けて渡すことで防げる。
- 引数インジェクション(CWE-88)は,引数として渡した値の先頭の「-」がコマンド自身にオプションとして解釈される問題であり,シェルを介さなくても起こる。
- 多くのコマンドでは,引数「--」がオプションの終わりを示し,それ以降の引数はオプションではなくファイル名などとして扱われる。
- 入力値の検証は,許可する文字や値を列挙する方式(許可リスト)の方が,危険な文字を列挙する方式(拒否リスト)よりも漏れが生じにくい。
引用符は,シェルが値を一つの引数として扱うようにするだけで,シェルが引用符を除いた後の値は「-aR」のままである。OWASP も,引数のエスケープで OS コマンドインジェクションは防げても,攻撃者は一つの引数を渡せると指摘しており,オプションとしての解釈は防げない。
フルパスでの指定は,PATH の操作によって意図しない同名のプログラムが起動されることを防ぐ対策である。正規の ls が起動されても,「-」で始まる引数はオプションとして解釈されるので,この問題は解消しない。
問題の原因はシェルのメタ文字ではなく,値の先頭の「-」がコマンドのオプションとして解釈されることである。メタ文字を拒否しても「-aR」は通過し,許可する文字を列挙する現在の検証方式よりも弱くなる。
引数を分けて渡しても,「-」で始まる値はコマンド自身がオプションとして解釈する(CWE-88)。「ls -l --」のように「--」でオプションの終わりを示すか,先頭の文字を英数字に限定すれば,値はファイル名として扱われる。
照合の根拠(5 件)
- エ(正解): 「--」を置けば以降の引数はファイル名として扱われ,先頭の「-」がオプションと解釈されない
Another option could be to add a "--" argument to the ls command, such as "ls -l --", so that any remaining arguments are treated as filenames, causing any leading "-" to be treated as part of a filename instead of another option.
CWE-88 · Demonstrative Examples, Example 1(新しいタブで開きます) - エ(正解): 先頭の文字を英数字に限定する検証も対策になる
Another fix might be to change the regular expression used in validate_name to force the first character of the filename to be a letter or number
CWE-88 · Demonstrative Examples, Example 1(新しいタブで開きます) - ア(誤り): 引用符で一つの引数にしても,攻撃者は一つの引数(-aR)を渡せる
Even though escapeshellarg() prevents OS Command Injection, an attacker can still pass a single argument to the command.
OWASP OS Command Injection Defense Cheat Sheet · Defense option 2(新しいタブで開きます) - イ(誤り): フルパス指定は起動するプログラムを固定するだけで,引数の検証にはならない
If starting a process is necessary, use a fixed, fully qualified executable path in FileName and set UseShellExecute = false . This starts the executable directly; it does not validate its arguments.
OWASP OS Command Injection Defense Cheat Sheet · .NET(新しいタブで開きます) - ウ(誤り): 推奨は許可する文字を列挙する方式であり,メタ文字を拒否する方式へ変えると弱くなる。しかも -aR はメタ文字を含まず通過する
Allowlist Regular Expression : Where a list of good, allowed characters and the maximum length of the string are defined.
OWASP OS Command Injection Defense Cheat Sheet · Defense option 3, Layer 2(新しいタブで開きます)
問題文の状況は CWE-88 の Example 1(validate_name が「-」始まりを許し「ls -l -aR」で再帰一覧が得られる)と同じで,原因は先頭の「-」がオプションと解釈されることなので,オプション解釈の終了か先頭文字の制限が対策になる。