str_replace() 在多字节字符串上危险吗?

2022-08-30 14:56:00

给定某些多字节字符集,我假设以下内容没有执行其预期操作是否正确?

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

特别是,如果输入的字符集可能具有有效字符(如0xbf5c),则攻击者可以注入0xbf22以获取0xbf5c22,留下有效字符后跟不带引号的双引号 (”)。

有没有一种简单的方法来缓解这个问题,或者我首先误解了这个问题?

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

编辑:就此而言,像preg_quote()这样的函数呢?它没有字符集参数,因此在这种情况下它似乎完全没用。当你没有选择将字符集限制为UTF-8时(是的,那会很好),看起来你真的是残疾人。在这种情况下,可以使用哪些替换和报价功能?


答案 1

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


答案 2

使用UTF-8和EUC-TW等合理的多字节编码,该代码是完全安全的,但对于Shift_JIS,GB *等损坏的编码则很危险。与其经历所有令人头疼的问题和开销来确保这些传统编码的安全,我建议只支持UTF-8。


推荐