str_replace() на многобайтовых строках опасно?

Учитывая определенные многобайтовые наборы символов, я прав, предполагая, что следующее не делает то, для чего оно предназначалось?

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

В частности, если ввод был в наборе символов, который мог бы иметь действительный символ, такой как 0xbf5c, то злоумышленник может ввести 0xbf22, чтобы получить 0xbf5c22, оставив действительный символ, за которым следует двойная кавычка без кавычек (").

Есть ли простой способ смягчить эту проблему, или я неправильно понимаю проблему в первую очередь?

(В моем случае строка входит в атрибут value тега ввода HTML: echo 'input type="text" value="' . $ String . '">';)

РЕДАКТИРОВАТЬ: В этом отношении, как насчет функции, как preg_quote()? Для этого нет аргумента charset, поэтому в этом сценарии он кажется совершенно бесполезным. Когда у вас нет возможности ограничить кодировку UTF-8 (да, это было бы неплохо), кажется, что вы действительно инвалиды. Какие функции замены и цитирования доступны в этом случае?

4 ответа

Решение

Нет, вы правы: использование однобайтовой строковой функции в многобайтовой строке может привести к неожиданному результату. Вместо этого используйте многобайтовые строковые функции, например mb_ereg_replace или же mb_split:

$string = mb_ereg_replace('"', '\\"', $string);
$string = implode('\\"', mb_split('"', $string));

Редактировать вот mb_replace реализация с использованием варианта split-join:

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,

Код совершенно безопасен для нормальных многобайтовых кодировок, таких как UTF-8 и EUC-TW, но опасен для сломанных, таких как Shift_JIS, GB* и т. Д. Вместо того, чтобы проходить через всю головную боль и накладные расходы, чтобы быть в безопасности с этими устаревшими кодировками, я Рекомендую только поддержку только UTF-8.

Вы можете использовать либо mb_ereg_replace сначала указав кодировку с mb_regex_encoding(), В качестве альтернативы, если вы используете UTF-8, вы можете использовать preg_replace с u модификатор.

Из того, что я понимаю, большая часть этого типа внедрения строк решается mysql_real_escape_string(); функция.

http://php.net/manual/en/function.mysql-real-escape-string.php

Другие вопросы по тегам