Miré por todas partes y no puedo encontrar la respuesta a mi pregunta.
Estoy usando el último PHP para scripting del lado del servidor y MySQL para mi base de datos. El conjunto de caracteres es utf8mb4
si eso marca una diferencia.
Hasta ahora, he usado declaraciones preparadas para protegerme de la inyección de SQL. Sin embargo, dado que la mayoría de mis consultas solo se ejecutan una vez, el código es realmente lento . Cuando uso $conn->query()
en su lugar, y $conn->real_escape_string()
para todas mis variables, es más rápido.
Sin embargo, $conn->real_escape_string()
también es lento porque hay un viaje de ida y vuelta en cada llamada. Pero no entiendo por qué es necesario un viaje de ida y vuelta porque creo que esa función de escape solo puede programarse en PHP.
Desde los documentos, una función se vería así:
Los caracteres codificados son NUL (ASCII 0), \ n, \ r, \, ', "y Control-Z.
function sanitize($str)
{
str_replace(array('\', "$sql = "UPDATE ipsum SET lorem=$str WHERE id=1337";
", "\n", "\r", "'", '"', "\x1a"), array('\\', '\0', '\n', '\r', "\'", '\"', '\Z'), $str);
}
Suponiendo que me asegure de que esté en la codificación correcta y que no esté vacía.
Esto se publicó como un comentario en uno de los documentos. Por cierto, str_replace
funciona con Unicode.
Sin embargo, pensé en algo que tiene un poco más de sentido. Mirando esta página , puedo estirar esto un lote más lejos. Para una declaración como esta:
function sanitize($str)
{
return "'" .str_replace(array("\", "'"), array("\\", "\'"), $str) . "'";
}
No puedo hacerlo (y estoy comprobando de antemano para asegurarme de que es un UTF-8):
function sanitize($str)
{
str_replace(array('\', "$sql = "UPDATE ipsum SET lorem=$str WHERE id=1337";
", "\n", "\r", "'", '"', "\x1a"), array('\\', '\0', '\n', '\r', "\'", '\"', '\Z'), $str);
}
¿Y eso evitará las inyecciones SQL? Por qué no? No puedo pensar en una entrada para la cual fallará.
Si no, ¿existe una mejor función de PHP que pueda proteger mejor contra la inyección de SQL?
Gracias de antemano! Puede probar SQL aquí .
ACTUALIZACIÓN: recibió las respuestas que esperaba. Para aclarar, no te estoy pidiendo que pronuncies tus predicaciones clásicas de "las declaraciones preparadas son lo mejor que hay que hacer o morir". Si quisiera eso, lo pediría en Yahoo! Respuestas y no aquí.
Me gustaría saber por qué mi método (el segundo) no es seguro (o si lo es). También sería bueno incluir una discusión de lo que real_escape_string
o declaraciones preparadas realmente hacen para sanear los datos. Tanto MySQL como PHP son de código abierto, y estoy seguro de que alguien sabe qué sucede cuando se llaman estas funciones.
Simplemente no entiendo por qué se necesita un viaje de ida y vuelta para desinfectar las cadenas. ¿Cómo puede un método así no ser implementado en PHP?
ACTUALIZACIÓN 2: He iterado a través de todos los caracteres Unicode (0x0000 a 0x1F77F, encontré esto en Wikipedia) y noté que, si real_escape_string()
solo escapa caracteres individuales y no frases (lo que de acuerdo con los documentos que hace), debajo de utf8mb4
charset, los caracteres que cambian son:
unicode 0 = > \ 0
unicode 10 = > \ n
unicode 13 = > \ r
unicode 26 = > \ Z
unicode 34 = > \ "
unicode 39 = > \ '
unicode 92 = > \\
Entonces, a pesar de que es utf8mb4
, no es diferente de lo que dicen los documentos (adivina porque UTF-8 es estándar). Entonces, ¿por qué esto no es implementable en PHP?
Aquí hay un secuencia de comandos PHP que combina todos estos Unicodes y los desinfecta. Aquí hay un violín de SQL .