むりくり array 攻撃と名づけてみる修行

PHP では GET や POST のリクエストとして配列を与えることができる。

http://〜/certain.php?a[x]=1&a[y]=2

この場合、PHP 側で

$a = $_GET['a'];

とした場合、$a の値は array( 'x' => 1, 'y' => 2 ) になっている。
したがって、$a を文字列だと決めつけて処理していると次の問題が生じうる。

  1. 文字列を期待する関数に配列を渡すことになり、PHP の各種警告が出る。
  2. データベースに Array という文字列が格納される。
  3. 正規表現で除外、などの文字列チェックをすり抜ける。
  4. 文字列置換による無害化をすり抜ける。

このように文字列であることを期待するパラメータに配列を送りつける攻撃方法をむりくり array 攻撃、と名づける。逆パターンとして、配列であることを期待するパラメータに文字列パラメータを送りつける方法があるが、これも広義のむりくり array 攻撃に含める。
リクエストパラメータに [] が付いていると配列に格納するのは PHP の言語仕様なので、この攻撃が成立するとすれば、単にやるべきことをやっていないだけであると知るべし。HTTP クライアントから送信される値を一切信用しないのは WEB アプリセキュリティの基本中の基本。

ただし、配列を文字列コンテキストで評価しても Array という文字列になるだけで、任意の文字列を挿入させられるわけではないので、単体でセキュリティ上の大きな問題にはなりにくい。

正しい対処方法は、配列が入ってくる可能性があることを常に意識し、文字列が来るはずのパラメータに配列が入ってきたらエラーにするか、デフォルトの文字列に落とし込むこと。どちらにするかはそのアプリの仕様による。
既存のサイトに対する対処療法としては、文字列を期待するパラメータについて

$a = $_GET['a'];

$a = '' + $_GET['a'];

として、無理やり文字列コンテキストで評価させることが考えられる。この場合、配列が入ってきた場合、$a の値は Array という文字列になる。
もう少し正しくやるには、is_array() で確認する。
逆パターン (配列を期待するところに文字列を入れられる) も同様。

なお、盲点になりがちだが、$_COOKIE も同様の処理がされるので要注意。と最後にさりげなく重要な情報を書いてみる。