php - special - ¿Str_replace() en cadenas de varios bytes es peligroso?
trim array php (4)
Dados ciertos conjuntos de caracteres multibyte, ¿tengo razón al suponer que lo siguiente no hace lo que estaba destinado a hacer?
$string = str_replace(''"'', ''//"'', $string);
En particular, si la entrada estaba en un conjunto de caracteres que podría tener un carácter válido como 0xbf5c, un atacante puede inyectar 0xbf22 para obtener 0xbf5c22, dejando un carácter válido seguido de una comilla doble sin comillas (").
¿Hay una manera fácil de mitigar este problema, o estoy entendiendo mal el problema en primer lugar?
(En mi caso, la cadena entra en el atributo de valor de una etiqueta de entrada HTML: echo ''input type = "text" value = "''. $ String. ''">'';)
EDIT: Para el caso, ¿qué pasa con una función como preg_quote ()? No hay un argumento de conjunto de caracteres para ello, por lo que parece totalmente inútil en este escenario. Cuando NO tienes la opción de limitar el juego de caracteres a UTF-8 (sí, eso sería bueno), parece que estás realmente discapacitado. ¿Qué funciones de reemplazar y citar están disponibles en ese caso?
El código es perfectamente seguro con codificaciones multibyte sanas como UTF-8 y EUC-TW, pero peligroso con las rotas como Shift_JIS, GB *, etc. Recomendaría solo soportar solo UTF-8.
No, tienes razón: el uso de una función de cadena de un solo byte en una cadena de varios bytes puede provocar un resultado inesperado. Utilice las funciones de cadena multibyte en su lugar, por ejemplo mb_ereg_replace
o mb_split
:
$string = mb_ereg_replace(''"'', ''//"'', $string);
$string = implode(''//"'', mb_split(''"'', $string));
Editar Aquí hay una implementación de mb_replace
utilizando la variante de unión dividida:
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 cuanto a la combinación de parámetros, esta función debería comportarse como el single_byte str_replace
.
Por lo que entiendo, gran parte de este tipo de inyección de cadenas se resuelve mediante mysql_real_escape_string (); función.
http://php.net/manual/en/function.mysql-real-escape-string.php
Puedes usar mb_ereg_replace
especificando primero el conjunto de caracteres con mb_regex_encoding()
. Alternativamente, si usa UTF-8, puede usar preg_replace
con el modificador u
.