前回,入力値検証をセキュリティ対策として実施すべき理由を説明する中で制御文字や不正な文字エンコーディングの問題を指摘した。今回は,その具体例として「ヌルバイト攻撃」と「冗長なUTF-8によるディレクトリ・トラバーサル」を説明する。

制御文字悪用の代表格「ヌルバイト攻撃」

 ヌルバイト攻撃とは,ASCIIコード0の文字(ヌル文字)を用いた攻撃である。リスト1に示すPHPスクリプトは,クエリー文字列pとして数値を受け取り,それを表示するというもの。結果を表示する前に正規表現関数eregを使って数字だけのデータかどうかをチェックし,数字でない場合にはエラーメッセージを表示するようになっている。通常,数字だけを使った攻撃は不可能であり,このような「安全な文字」だけを許可するような検査方法を一般に「ホワイトリスト検査」と呼ぶ。

リスト1●数値を表示するPHPスクリプト
リスト1●数値を表示するPHPスクリプト

 リスト1はホワイトリスト検査の典型例だが,このサンプルにはぜい弱性が潜んでいる。パラメータpを以下のように指定するとダイアログ上にクッキー値が表示される。つまり,クロスサイト・スクリプティング(XSS)のぜい弱性である(図1)。


図1●NULLバイト攻撃によるXSS
図1●NULLバイト攻撃によるXSS

 %00はヌル文字をパーセント・エンコードしたもので,入力文字列の終端を意味する制御コードである。このためPHPの関数eregはヌル文字を入力文字列の終端とみなし,それより後の文字列は検査しない。ヌル文字以降に攻撃用コードが隠されていても,eregでは検査できないのだ。このようにヌル文字を用いた攻撃は「ヌルバイト攻撃」(null byte attack)あるいは「ヌル・インジェクション」(null injection)と呼ばれる。