ユーザーの投稿データは汚い
なんて書くと、ユーザーから「なんだと! 傲慢な開発者め!」と言われそう。
だが、これは事実である。
ユーザーの投稿するデータはすべて汚れているという前提に立つのがセキュリティの基本であると言える。
よって、このデータをキレイキレイにしなければならない。
汚れたデータからクリーンなデータを抽出する
汚れているデータからクリーンなデータを抽出するには、バリデーションとサニタイズの両方をやる必要がある。
まずバリデーションでデータを検証し、不正なデータならエラーにする。
その後、データをサニタイズで無害化し、クリーンなデータとして扱う。
// dirty_int は汚れている
$dirty_int = $_POST['dirty_int'];
// バリデーション
// $dirty_int が不正な整数だったら false が返る
$int = filter_var($drity_int, FILTER_VALIDATE_INT);
if ($int === false) {
throw new \Exception('validation error');
}
// サニタイズ
// 値を範囲内にする
if ($int > 100) {
$int = 100;
} else if ($int < -100) {
$int = -100;
}
// クリーンデータとして管理
$clean_int = $int;
問題はデータが単数でなく複数の場合である。
$_POSTには配列もデータとして受け取ることができる。
よって、この配列からクリーンデータを抽出しないといけない。
// クリーンデータの格納先
$clean_data = [];
// dirty_data は汚れている
$dirty_data = $_POST['dirty_data'];
$number = filter_var($dirty_data['number'], FILTER_VALIDATE_INT);
if ($number === false) {
throw new \Exception('invalid data number');
}
if ($number > 100) {
$number = 100;
} else if ($number < -100) {
$number = -100;
}
// number はキレイ!
$clean_data['number'] = $number;
バリデーションとサニタイズは両方やったほうがいいの?
サニタイズだけしてデータを無害化し、バリデーションは行わないという選択肢もある。
だがこれだと不正データの投稿を検出できない。
バリデーションで不正データの投稿を検出し、エラーにしてログを残すことで、アタッカーの痕跡を残すことができる。
アタッカーの攻撃の痕跡を知るのはセキュリティ上、非常に重要なので、バリデーションによってこれを検出した方がいいだろう。