筆者はここ数年、
残念なことに最近になっても不正な文字エンコーディングが入力される可能性を考慮していないことによる脆弱性が、
マルチバイト文字エンコーディングは最初または前方に配置されたバイトで1文字が何バイトで構成されるか決まります。この性質を利用してマルチバイト文字列の開始バイトでエスケープ文字を無効化することが可能な場合があります。
Shift JIS等のマルチバイト文字に含まれる特殊文字
addslashes('表'); // SJIS文字エンコーディング
「表」
SJISエンコーディングでは0x95はマルチバイト文字の開始バイトと解釈されるので、
"SJISの0x95"
を
"SJISの0x95+0x22
と解釈してしまい、
PHPには文字エンコーディングが正しいか確認するmb_
$_FILES以外の$_POST, $_GET, $_COOKIEに保存されたデータはすべて文字として扱えるデータである、
// 入力文字列のエンコーディングを設定
define('INPUT_ENCODING', 'UTF-8');
function input_encoding_check_cb($k, $v) {
// input_encoding_checkのコールバック関数
if (!mb_check_encoding($k, INPUT_ENCODING) || !mb_check_encoding($v, INPUT_ENCODING)) {
trigger_error('不正な文字エンコーディングを検出しました');
die('System detected some errors');
}
}
function input_encoding_check($v) {
array_walk_recursive($v, 'input_encoding_check_cb');
}
input_encoding_check($_GET);
input_encoding_check($_POST);
input_encoding_check($_COOKIE);
対策のまとめ
- 入力文字列は必ず文字エンコーディングが正しいか確認する
- 可能な限り文字エンコーディングは統一する
- SJIS、
EUC-JP、 ISO-2022-JPを取り扱う場合、 特に注意する - 正しい文字エンコーディングのみ保存可能な仕組み利用する
(データベースなどのバイナリ型を利用して不正な文字エンコーディングの文字列を保存しない)