Cuando se trata de consultas de bases de datos, siempre intente utilizar consultas parametrizadas preparadas. Las bibliotecas mysqli
y lo PDO
admiten. Esto es infinitamente más seguro que usar funciones de escape como mysql_real_escape_string
.
Sí, mysql_real_escape_string
es efectivamente solo una función de escape de cadenas. No es una fórmula mágica. Todo lo que hará es escapar de los caracteres peligrosos para que sean seguros de usar en una sola cadena de consulta. Sin embargo, si no desinfecta sus entradas de antemano, será vulnerable a ciertos vectores de ataque.
Imagina el siguiente SQL:
$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);
Debería poder ver que esto es vulnerable a la explotación.
Imagina que el id
parámetro contiene el vector de ataque común:
1 OR 1=1
No hay caracteres de riesgo para codificar, por lo que pasará directamente a través del filtro de escape. Dejándonos:
SELECT fields FROM table WHERE id= 1 OR 1=1
Que es un hermoso vector de inyección SQL y permitiría al atacante devolver todas las filas. O
1 or is_admin=1 order by id limit 1
que produce
SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1
Lo que permite al atacante devolver los datos del primer administrador en este ejemplo completamente ficticio.
Si bien estas funciones son útiles, deben usarse con cuidado. Debe asegurarse de que todas las entradas web estén validadas hasta cierto punto. En este caso, vemos que podemos ser explotados porque no verificamos que una variable que estábamos usando como número fuera en realidad numérica. En PHP debería utilizar ampliamente un conjunto de funciones para comprobar que las entradas sean enteros, flotantes, alfanuméricos, etc. Pero cuando se trata de SQL, preste más atención al valor de la declaración preparada. El código anterior habría sido seguro si fuera una declaración preparada, ya que las funciones de la base de datos habrían sabido que 1 OR 1=1
no es un literal válido.
En cuanto a htmlspecialchars()
. Ese es un campo minado en sí mismo.
Existe un problema real en PHP ya que tiene una selección completa de diferentes funciones de escape relacionadas con html y no hay una guía clara sobre exactamente qué funciones hacen qué.
En primer lugar, si está dentro de una etiqueta HTML, está en un verdadero problema. Mirar
echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';
Ya estamos dentro de una etiqueta HTML, por lo que no necesitamos <o> para hacer nada peligroso. Nuestro vector de ataque podría serjavascript:alert(document.cookie)
Ahora el HTML resultante parece
<img src= "javascript:alert(document.cookie)" />
El ataque llega directo.
Se pone peor. ¿Por qué? porque htmlspecialchars
(cuando se llama de esta manera) solo codifica comillas dobles y no simples. Entonces si tuviéramos
echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";
Nuestro malvado atacante ahora puede inyectar parámetros completamente nuevos
pic.png' onclick='location.href=xxx' onmouseover='...
Nos da
<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />
En estos casos, no existe una fórmula mágica, solo tienes que corregir la entrada tú mismo. Si intentas filtrar los personajes malos, seguramente fallarás. Adopte un enfoque de lista blanca y deje pasar solo los caracteres que sean buenos. Mire la hoja de trucos de XSS para ver ejemplos sobre cómo diversos vectores pueden ser
Incluso si utiliza htmlspecialchars($string)
etiquetas fuera de HTML, sigue siendo vulnerable a los vectores de ataque de conjuntos de caracteres de varios bytes.
Lo más eficaz que puede ser es utilizar una combinación de mb_convert_encoding y htmlentities de la siguiente manera.
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');
Incluso esto deja a IE6 vulnerable, debido a la forma en que maneja UTF. Sin embargo, puede recurrir a una codificación más limitada, como ISO-8859-1, hasta que el uso de IE6 disminuya.
Para un estudio más profundo de los problemas multibyte, consulte https://stackoverflow.com/a/12118602/1820