str_replace()对多字节字符串有危险吗?

use*_*885 23 php multibyte

鉴于某些多字节字符集,我是否正确假设以下内容不符合预期目的?

$string = str_replace('"', '\\"', $string);
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑:就此而言,像preg_quote()这样的函数呢?它没有charset论据,因此在这种情况下似乎完全没用.如果你没有选择将字符集限制为UTF-8(是的,这很好),你好像很残疾.在这种情况下可以使用哪些替换和引用功能?

Gum*_*mbo 28

不,你是对的:在多字节字符串上使用单字节字符串函数可能会导致意外结果.例如,使用多字节字符串函数,mb_ereg_replacemb_split:

$string = mb_ereg_replace('"', '\\"', $string);
$string = implode('\\"', mb_split('"', $string));
Run Code Online (Sandbox Code Playgroud)

编辑     这是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;
}
Run Code Online (Sandbox Code Playgroud)

关于参数组合,此函数应该像单字节一样str_replace.

  • 另外如[str_replace可以安全地用于UTF-8编码的字符串,如果它只给出有效的UTF-8编码字符串作为参数?](http://stackoverflow.com/questions/2652193/can-str-replace-安全地使用-ut-8-encoded-string-if-only-only-valid),只要输入是有效的UTF-8就不需要mb_str_replace.参见[phpwact.org](http://www.phpwact.org/php/i18n/charsets#checking_utf-8_for_well_formedness)和[hfuecks在php手册]的评论(http://www.php.net/manual /en/reference.pcre.pattern.modifiers.php#54805)用于检查(in)有效UTF-8的方法. (4认同)
  • PHP 中没有 mb_str_replace (2认同)

R..*_*R.. 5

该代码是完全安全的理智多字节编码方式,如UTF-8和EUC-TW,但危险破碎的像SHIFT_JIS,GB*,等等.而不是去通过所有的头痛和开销是安全与这些遗留编码,我建议只支持UTF-8.

  • @TimoHuovinen:对于必须处理非 UTF-8 编码数据的应用程序,最简单的解决方案是在输入阶段重新编码,以便在处理时它是 UTF-8 格式。 (3认同)