29

给定某些多字节字符集,我是否正确假设以下内容没有达到预期的效果?

$string = str_replace('"', '\\"', $string);

特别是,如果输入的字符集中可能具有像 0xbf5c 这样的有效字符,那么攻击者可以注入 0xbf22 来获取 0xbf5c22,留下一个有效字符后跟一个不带引号的双引号 (")。

有没有一种简单的方法可以缓解这个问题,还是我一开始就误解了这个问题?

(在我的例子中,字符串进入 HTML 输入标签的 value 属性:echo 'input type="text" value="' . $string . '">';)

编辑:就此而言,像 preg_quote() 这样的函数呢?它没有字符集参数,因此在这种情况下它似乎完全没用。当您没有将字符集限制为 UTF-8 的选项时(是的,那很好),您似乎真的有缺陷。在这种情况下可以使用哪些替换和引用功能?

4

3 回答 3

30

不,你是对的:对多字节字符串使用单字节字符串函数可能会导致意外结果。请改用多字节字符串函数,例如mb_ereg_replaceor 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

于 2010-09-24T10:06:46.783 回答
8

对于像 UTF-8 和 EUC-TW 这样的健全的多字节编码,该代码是完全安全的,但对于像 Shift_JIS、GB* 等损坏的多字节编码是危险的。而不是通过所有的头痛和开销来确保这些旧编码的安全,我建议只支持 UTF-8。

于 2011-01-17T05:29:04.080 回答
3

您可以mb_ereg_replace通过首先指定字符集来使用mb_regex_encoding(). 或者,如果您使用 UTF-8,则可以使用preg_replace修饰符u

于 2010-09-24T10:09:17.900 回答