鉴于某些多字节字符集,我是否正确假设以下内容不符合预期目的?
$string = str_replace('"', '\\"', $string);
特别是,如果输入是一个字符集,可能有一个像0xbf5c这样的有效字符,那么攻击者可以注入0xbf22来获取0xbf5c22,留下一个有效字符后跟一个不带引号的双引号(“)。
是否有一种简单的方法可以缓解这个问题,或者我是否首先误解了这个问题?
(在我的例子中,字符串进入HTML输入标签的value属性:echo'input type =“text”value =“'。$ string。'”>';)
编辑:就此而言,像preg_quote()这样的函数呢?它没有charset论据,因此在这种情况下似乎完全没用。如果你没有选择将字符集限制为UTF-8(是的,这很好),你好像很残疾。在这种情况下有哪些替换和引用功能?
答案 0 :(得分:26)
不,你是对的:在多字节字符串上使用单字节字符串函数可能会导致意外结果。请改用multibyte string functions,例如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;
}
关于参数组合,此函数应该像单字节str_replace
一样。
答案 1 :(得分:5)
使用UTF-8和EUC-TW这样的理智多字节编码,代码非常安全,但对于像Shift_JIS,GB *等已破坏的代码很危险。为了安全地使用这些遗留编码,我会建议只支持UTF-8。
答案 2 :(得分:3)
首先使用mb_ereg_replace
指定字符集,您可以使用mb_regex_encoding()
。或者,如果您使用UTF-8,则可以将preg_replace
与u
修饰符一起使用。
答案 3 :(得分:-4)
根据我的理解,这种类型的字符串注入很多都是由mysql_real_escape_string()解决的;功能。
http://php.net/manual/en/function.mysql-real-escape-string.php