Multibyte文字列上のstr_replace()危険?
質問
特定のマルチバイト文字セットを考えると、以下が意図したことをしていないと仮定するのは正しいですか?
$string = str_replace('"', '\\"', $string);
特に、入力が0xBF5Cのような有効な文字を持つ可能性のある文字セットにある場合、攻撃者は0xBF22を注入して0xBF5C22を取得でき、有効な文字が残り、引用されていない二重引用( ")が残ります。
この問題を軽減する簡単な方法はありますか、それともそもそも問題を誤解していますか?
(私の場合、文字列はhtml入力タグの値属性になります:echo '入力型= "text" value = "'。$ string '">';)
編集:そのため、preg_quote()のような関数はどうですか?それについては炭絵の議論はないので、このシナリオではまったく役に立たないようです。 CharsetをUTF-8に制限するオプションがない場合(はい、それはいいでしょう)、あなたは本当に障害者であるように見えます。その場合、どのような置き換えおよび引用機能が利用可能ですか?
解決
いいえ、あなたは正しいです:マルチバイト文字列にsingleByte文字列関数を使用すると、予期しない結果が生じる可能性があります。使用 マルチバイト文字列関数 代わりに、たとえば mb_ereg_replace
また mb_split
:
$string = mb_ereg_replace('"', '\\"', $string);
$string = implode('\\"', mb_split('"', $string));
編集これが次のとおりです mb_replace
分割結合バリアントを使用した実装:
function mb_replace($search, $replace, $subject, &$count=0) {
if (!is_array($search) && is_array($replace)) {
return false;
}
if (is_array($subject)) {
// call mb_replace for each single string in $subject
foreach ($subject as &$string) {
$string = &mb_replace($search, $replace, $string, $c);
$count += $c;
}
} elseif (is_array($search)) {
if (!is_array($replace)) {
foreach ($search as &$string) {
$subject = mb_replace($string, $replace, $subject, $c);
$count += $c;
}
} else {
$n = max(count($search), count($replace));
while ($n--) {
$subject = mb_replace(current($search), current($replace), $subject, $c);
$count += $c;
next($search);
next($replace);
}
}
} else {
$parts = mb_split(preg_quote($search), $subject);
$count = count($parts)-1;
$subject = implode($replace, $parts);
}
return $subject;
}
パラメーターの組み合わせに関しては、この関数はsingleByteのように動作する必要があります str_replace
.
他のヒント
コードは完全に安全です 正気 UTF-8やEUC-TWなどのマルチバイトエンコーディングですが、危険です 壊れた Shift_jis、Gb*などのようなもの。これらのレガシーエンコーディングで安全であるためにすべての頭痛と頭上を通過するのではなく、UTF-8のみをサポートすることをお勧めします。
どちらかを使用できます mb_ereg_replace
最初にcharsetを指定することにより mb_regex_encoding()
. 。または、UTF-8を使用する場合は、使用できます preg_replace
とともに u
修飾子。
私が理解していることから、このタイプの文字列注入の多くは、mysql_real_escape_string()によって解決されます。働き。
http://php.net/manual/en/function.mysql-real-escape-string.php