str_replace () sur les chaînes multi-octets dangereux?
Question
Compte tenu de certains jeux, ai-je raison de caractères multi-octets en supposant que ce qui suit ne fait pas ce qu'il était censé faire?
$string = str_replace('"', '\\"', $string);
En particulier, si l'entrée était dans un jeu de caractères qui pourraient avoir un caractère valide comme 0xbf5c, donc un attaquant peut injecter 0xbf22 pour obtenir 0xbf5c22, laissant un caractère valide suivi d'un unquoted guillemet ( ").
Y at-il un moyen facile d'atténuer ce problème, ou que je comprends mal la question en premier lieu?
(Dans mon cas, la chaîne va dans l'attribut de valeur d'une balise d'entrée HTML: ' ". $ String'" echo input type = valeur "text" = '>';)
EDIT: Pour cette question, qu'en fonction comme preg_quote ()? Il n'y a pas argument charset pour elle, il semble tout à fait inutile dans ce scénario. Lorsque vous n'avez la possibilité de limiter charset UTF-8 (oui, ce serait bien), il semble que vous êtes vraiment handicapé. Que remplacer et les fonctions sont disponibles en citant ce cas?
La solution
Non, vous avez raison: l'aide d'une fonction de chaîne singlebyte sur une chaîne de caractères multi-octets peut causer un résultat inattendu. Utilisez le fonctions de chaîne multi-octets au lieu, par exemple mb_ereg_replace ou href="http://php.net/mb_split" rel="noreferrer"> mb_split
:
$string = mb_ereg_replace('"', '\\"', $string);
$string = implode('\\"', mb_split('"', $string));
Modifier Voici une implémentation mb_replace
en utilisant la variante 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;
}
En ce qui concerne la combinaison de paramètres, cette fonction doit se comporter comme le str_replace
de singlebyte.
Autres conseils
Le code est parfaitement sûr avec sain d'esprit multi-octets codages comme UTF-8 et EUC-TW, mais dangereux avec cassés les comme Shift_JIS, GB *, etc., plutôt que de passer par tous les maux de tête et des frais généraux pour être en sécurité avec ces anciens codages, je recommande simplement soutenir que UTF-8.
Vous pouvez utiliser soit mb_ereg_replace
d'abord spécifier le charset avec mb_regex_encoding()
. Alternativement, si vous utilisez UTF-8, vous pouvez utiliser preg_replace
avec le modificateur u
.
D'après ce que je comprends, une grande partie de ce type d'injection de chaîne est résolu par le mysql_real_escape_string (); une fonction.
http://php.net/manual/en/ function.mysql-real-évasion-string.php