tipos reales proteger mysqli_real_escape_string inyeccion injection evitar ejemplos contra php security xss sql-injection

reales - ¿Htmlspecialchars y mysql_real_escape_string mantienen mi código PHP a salvo de la inyección?



sql injection ejemplos reales (6)

¿Por qué, oh POR QUÉ, no incluirías comillas alrededor de la entrada del usuario en tu declaración SQL? parece bastante tonto no hacerlo! incluir citas en su declaración sql haría "1 o 1 = 1" un intento infructuoso, ¿no?

Entonces, dirá: "¿Qué pasa si el usuario incluye una cita (o comillas dobles) en la entrada?"

Bien, solución fácil para eso: simplemente elimine las cotizaciones ingresadas por el usuario. por ejemplo: input =~ s/''//g; . ahora, me parece que de todos modos, la entrada del usuario estaría asegurada ...

Hoy se hizo una pregunta sobre las estrategias de validación de entrada en las aplicaciones web .

La respuesta principal, al momento de escribir, sugiere en PHP solo el uso de htmlspecialchars y mysql_real_escape_string .

Mi pregunta es: ¿esto siempre es suficiente? ¿Hay más que deberíamos saber? ¿Dónde se rompen estas funciones?


Además de la excelente respuesta de Cheekysoft:

  • Sí, te mantendrán a salvo, pero solo si se usan de forma absolutamente correcta. Úselos de forma incorrecta y seguirá siendo vulnerable, y puede tener otros problemas (por ejemplo, corrupción de datos)
  • Utilice en su lugar consultas parametrizadas (como se indicó anteriormente). Puede usarlos a través de, por ejemplo, PDO o mediante un contenedor como PEAR DB
  • Asegúrese de que magic_quotes_gpc y magic_quotes_runtime estén desactivados en todo momento y nunca se enciendan accidentalmente, ni siquiera brevemente. Estos son un intento temprano y profundamente equivocado de los desarrolladores de PHP para evitar problemas de seguridad (que destruyen los datos)

No hay realmente una bala de plata para prevenir la inyección de HTML (por ejemplo, scripts de sitios cruzados), pero es posible que pueda lograrlo más fácilmente si está usando una biblioteca o sistema de plantillas para generar HTML. Lea la documentación de cómo escapar de las cosas de manera apropiada.

En HTML, las cosas deben escaparse de manera diferente según el contexto. Esto es especialmente cierto de las cadenas que se colocan en Javascript.


Cuando se trata de consultas a bases de datos, siempre intente utilizar consultas preparadas y parametrizadas. Las bibliotecas mysqli y PDO admiten. Esto es infinitamente más seguro que usar funciones de escape como mysql_real_escape_string .

Sí, mysql_real_escape_string es solo una función de escape de cadenas. No es una bala mágica. Todo lo que hará es escapar de los caracteres peligrosos para que puedan ser seguros de usar en una sola cadena de consulta. Sin embargo, si no desinfecta sus entradas de antemano, entonces será vulnerable a ciertos vectores de ataque.

Imagine 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 explotar.
Imagine que el parámetro id contiene el vector de ataque común:

1 OR 1=1

No hay caracteres peligrosos 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 encantador 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 le permite al atacante devolver los detalles 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 utilizamos como número sea en realidad numérica. En PHP, debe usar ampliamente un conjunto de funciones para verificar que las entradas sean enteros, flotantes, alfanuméricos, etc. Pero cuando se trata de SQL, preste 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 de minas propio.

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 qué funciones hacen qué.

En primer lugar, si estás dentro de una etiqueta HTML, estás en un problema real. Mirar

echo ''<img src= "'' . htmlspecialchars($_GET[''imagesrc'']) . ''" />'';

Ya estamos dentro de una etiqueta HTML, por lo que no necesitamos <o> hacer nada peligroso. Nuestro vector de ataque podría ser javascript:alert(document.cookie)

Ahora el HTML resultante se ve como

<img src= "javascript:alert(document.cookie)" />

El ataque pasa directamente.

Se pone peor. ¿Por qué? porque htmlspecialchars (cuando se llama de esta manera) solo codifica comillas dobles y no solo. Entonces si tuviéramos

echo "<img src= ''" . htmlspecialchars($_GET[''imagesrc'']) . ". />";

Nuestro malvado atacante ahora puede inyectar nuevos parámetros

pic.png'' onclick=''location.href=xxx'' onmouseover=''...

Nos da

<img src=''pic.png'' onclick=''location.href=xxx'' onmouseover=''...'' />

En estos casos, no hay una solución mágica, solo tiene que santificar la entrada usted mismo. Si intentas filtrar los caracteres incorrectos, seguramente fallarás. Tome un enfoque de lista blanca y solo deje pasar los caracteres que son buenos. Mire la hoja de trucos de XSS para ver ejemplos de cómo pueden ser diversos vectores

Incluso si usa htmlspecialchars($string) fuera de las etiquetas HTML, sigue siendo vulnerable a los vectores de ataque de juego de caracteres de varios bytes.

Lo más efectivo que puede ser es usar 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 IE6 vulnerable, debido a la forma en que maneja UTF. Sin embargo, podría 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://.com/a/12118602/1820


Definitivamente estoy de acuerdo con las publicaciones anteriores, pero tengo una pequeña cosa que añadir en respuesta a la respuesta de Cheekysoft, específicamente:

Cuando se trata de consultas a bases de datos, siempre intente utilizar consultas preparadas y parametrizadas. Las bibliotecas mysqli y PDO lo admiten. Esto es infinitamente más seguro que usar funciones de escape como mysql_real_escape_string.

Sí, mysql_real_escape_string es solo una función de escape de cadenas. No es una bala mágica. Todo lo que hará es escapar de los caracteres peligrosos para que puedan ser seguros de usar en una sola cadena de consulta. Sin embargo, si no desinfecta sus entradas de antemano, entonces será vulnerable a ciertos vectores de ataque.

Imagine el siguiente SQL:

$ result = "SELECCIONAR campos DESDE la tabla WHERE id =" .mysql_real_escape_string ($ _ POST [''id'']);

Debería poder ver que esto es vulnerable a explotar. Imagine que el parámetro id contiene el vector de ataque común:

1 OR 1 = 1

No hay caracteres peligrosos para codificar, por lo que pasará directamente a través del filtro de escape. Dejándonos:

SELECCIONAR campos FROM table DONDE id = 1 OR 1 = 1

Codifiqué una pequeña función rápida que puse en mi clase de base de datos que eliminará cualquier cosa que no sea un número. Utiliza preg_replace, por lo que hay una función un poco más optimizada, pero funciona en una pizca ...

function Numbers($input) { $input = preg_replace("/[^0-9]/","", $input); if($input == '''') $input = 0; return $input; }

Entonces, en lugar de usar

$ result = "SELECCIONAR campos FROM table WHERE id =" .mysqlrealescapestring ("1 OR 1 = 1");

yo usaría

$ result = "SELECCIONAR campos FROM table WHERE id =" .Numbers ("1 OR 1 = 1");

y ejecutaría la consulta de forma segura

SELECCIONAR campos FROM table DONDE id = 111

Claro, eso solo impidió que se muestre la fila correcta, pero no creo que sea un gran problema para quien intente inyectar sql en su sitio;)


Una pieza importante de este rompecabezas es contextos. Alguien que envíe "1 OR 1 = 1" como ID no es un problema si cita todos los argumentos en su consulta:

SELECT fields FROM table WHERE id=''".mysql_real_escape_string($_GET[''id''])."''"

Lo que resulta en:

SELECT fields FROM table WHERE id=''1 OR 1=1''

que es ineficaz Como está escapando de la cadena, la entrada no puede salir del contexto de cadena. He probado esto hasta la versión 5.0.45 de MySQL, y usar un contexto de cadena para una columna entera no causa ningún problema.


$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET[''id''];

Funciona bien, incluso mejor en sistemas de 64 bits. Sin embargo, tenga cuidado con las limitaciones de su sistema para tratar grandes números, pero para las ID de las bases de datos, esto funciona muy bien el 99% del tiempo.

Debería utilizar una única función / método para limpiar sus valores también. Incluso si esta función es solo un contenedor para mysql_real_escape_string (). ¿Por qué? Porque un día, cuando se encuentra un exploit para su método preferido de limpieza de datos, solo tiene que actualizarlo en un lugar, en lugar de buscarlo y reemplazarlo en todo el sistema.