[PHP-users 15448]$HTTP_POST_VARSなどをarray_map()で処理する場合の問題について
Osamu Shigematsu
m5issige @ mr.hitachi-medical.co.jp
2003年 5月 22日 (木) 19:05:58 JST
こんにちは。重松です。
(かなり振りが長いのですが。。。)
GET/POST/Cookie のデータをまとめて sanitize する必要があります。
この処理は、以下の要件を満たせればと思っています。
- PHP 4 以降でなるべく幅広く使用可能
- $HTTP_GET_VARS ...etc を使う
- magic_quotes_gpc の設定に依存しない (強制 OFF)
(pukiwiki init.php 1.42 2003/04/30 より引用)
137 /////////////////////////////////////////////////
138 // 入力値の整形
139 if (get_magic_quotes_gpc()) {
140 $get = $post = $cookie = array();
141 foreach($HTTP_GET_VARS as $key => $value) {
142 if (!is_array($value)) {
143 $get[$key] = stripslashes($value);
144 }
145 }
146 foreach($HTTP_POST_VARS as $key => $value) {
147 $post[$key] = stripslashes($value);
148 }
149 foreach($HTTP_COOKIE_VARS as $key => $value) {
150 $cookie[$key] = stripslashes($value);
151 }
152 }
153 else {
154 $post = is_array($HTTP_POST_VARS) ? $HTTP_POST_VARS : array();
155 $get = is_array($HTTP_GET_VARS) ? $HTTP_GET_VARS : array();
156 $cookie = is_array($HTTP_COOKIE_VARS) ? $HTTP_COOKIE_VARS : array();
157 }
上記、pukiwiki のコードを参考にしようと思いましたが、
foreach を使っているので低速ですし、
それ以前の問題として、配列の入れ子に対処していないと思ます。
このことは、NULL byte attack 脆弱性 (GET)、
データの破損 (POST/Cookie) を意味すると思います。
汎用ではないのだから、仕方ないのかもしれませんが、
自作する必要がでてきました。
そこで、
<?php
// dump.cgi
header('Content-type: plain/text');
var_dump($HTTP_GET_VARS);
?>
というスクリプトを用意して、コマンドラインから、
$ w3m http://localhost/dump.cgi?x[][][]=x
として簡単に配列を入れ子にできることは確認できました。
# php3 だとできなかったと記憶しています。
また、
$ w3m http://localhost/dump.cgi?
では、空配列、
$ w3m http://localhost/dump.cgi?x
では、x がキーで、データが空の配列が返され、
常に配列であることを確認しました。
また、マニュアルには明記されていないようですが、array_map() は
配列が入れ子になっていても、すべての配列でない要素に対して、
再帰的に指定された関数を呼び出すようです。
(PHP 4.3.2RC2 でテストしました)
[PHP-users 10914] からのスレッドを踏まえると、foreach に対し、
array_map() を使用するのは、速度の面でも大きなアドバンテージがあります。
以上の私の環境に基づく事実、
(1) $HTTP_XXX_VARS は常に配列
(2) array_map() は高速で、入れ子の問題も解決
から、array_map() を使いたいと思ったのですが、
[PHP-users 13915] からの一連のスレッドを見ると、array_map() は
参照渡し仕様上できない、ということのようです。
振りが大変長くなりましたが、
(1), (2) は、そうであると期待して差し障りはありませんか?
$HTTP_GET_VARS あたりは、値渡しで、上書きは可能でしょうか?
それとも、一旦コピーをとる必要があるのでしょうか?
実際には以下のコードで処理したいと考えています。
アドバイスよろしくお願いいたします。
function remove_null($str) {
return str_replace("\0", ``, $str);
}
function sanitize($ary) {
if (get_magic_quotes_gpc()) {
$ary = array_map('stripslashes', $ary);
}
return array_map('remove_null', $ary);
}
$get = sanitize($HTTP_GET_VARS); // 値渡しになる?
--
Osamu Shigematsu <m5issige @ mr.hitachi-medical.co.jp>
PHP-users メーリングリストの案内