tipos reales inyeccion injection evitar ejemplos comandos php mysql mysqli sql-injection

php - reales - ¿Debo protegerme contra la inyección de SQL si utilicé un menú desplegable?



sql injection ejemplos reales (11)

Entiendo que NUNCA debe confiar en la información del usuario de un formulario, principalmente debido a la posibilidad de inyección SQL.

Sin embargo, ¿esto también se aplica a un formulario donde la única entrada proviene de un menú desplegable (ver a continuación)?

Estoy guardando $_POST[''size''] en una sesión que luego se usa en todo el sitio para consultar las distintas bases de datos (con una consulta Select de mysqli ) y cualquier inyección de SQL definitivamente dañaría (posiblemente).

No hay un área para la entrada del usuario tipeado para consultar las bases de datos, solo listas desplegables.

<form action="welcome.php" method="post"> <select name="size"> <option value="All">Select Size</option> <option value="Large">Large</option> <option value="Medium">Medium</option> <option value="Small">Small</option> </select> <input type="submit"> </form>


Sí, necesitas protegerte contra esto.

Déjame mostrarte por qué, usando la consola de desarrollador de Firefox:

Si no limpia estos datos, su base de datos será destruida. (Esta podría no ser una declaración de SQL totalmente válida, pero espero haber aclarado mi punto).

El hecho de que haya limitado las opciones disponibles en su menú desplegable no significa que haya limitado los datos que puedo enviar a su servidor.

Si trataste de restringir este comportamiento de uso adicional en tu página, mis opciones incluyen deshabilitar ese comportamiento, o simplemente escribir una solicitud HTTP personalizada en tu servidor que imite de todos modos el envío de este formulario. Hay una herramienta llamada curl usada exactamente para eso, y creo que el comando para enviar esta inyección de SQL se parecería a esto:

curl --data "size=%27%29%3B%20DROP%20TABLE%20*%3B%20--" http://www.example.com/profile/save

(Esto podría no ser un comando curl totalmente válido, pero de nuevo, espero haber llegado a un punto).

Entonces, voy a reiterar:

NUNCA confíes en la entrada del usuario. SIEMPRE protégete

No asuma que cualquier entrada del usuario es segura. Es potencialmente inseguro, incluso si llega por algún medio que no sea un formulario. Nada de eso es lo suficientemente confiable para evitar protegerse de la inyección de SQL.


Como esta pregunta fue etiquetada con sql-injection , aquí hay una respuesta con respecto a este tipo particular de ataque:

Como se le dijo en los comentarios, debe usar declaraciones preparadas para cada una de las consultas que involucren datos variables, sin excepciones .

Independientemente de cualquier cosa HTML!
Es esencial comprender que las consultas SQL deben formatearse correctamente independientemente de cualquier factor externo, ya sea de entrada HTML o cualquier otra cosa.

Aunque puede utilizar listas blancas sugeridas en otras respuestas para el propósito de validación de entrada, no debería afectar ninguna acción relacionada con SQL ; deben permanecer igual, sin importar si valida o no la entrada de HTML. Significa que todavía tiene que usar declaraciones preparadas al agregar cualquier variable en la consulta.

Aquí puede encontrar una explicación completa, por qué las declaraciones preparadas son imprescindibles y cómo usarlas correctamente, y dónde no son aplicables, y qué hacer en ese caso: Guía del autoestopista para la protección de inyección SQL

Además, esta pregunta fue etiquetada con mysqli . Sobre todo por accidente, supongo, pero de todos modos, tengo que advertirte que raw mysqli no es una sustitución adecuada para las antiguas funciones mysq_ * . Simplemente porque si se usa en el viejo estilo, no agregará seguridad. Si bien es compatible con las declaraciones preparadas, es doloroso y problemático, hasta el punto de que el usuario promedio de PHP simplemente no puede esforzarse en absoluto. Por lo tanto, si no hay ninguna ORM o algún tipo de biblioteca de abstracción, entonces PDO es su única opción.


El hecho de que haya restringido al usuario a solo usar valores de una cierta lista desplegable es irrelevante. Un usuario técnico puede capturar la solicitud http enviada a su servidor antes de que abandone su red, modificarla usando una herramienta como un servidor proxy local y luego continuarla en su camino. Con la solicitud modificada, pueden enviar valores de parámetros que no son los que ha especificado en la lista desplegable. Los desarrolladores deben tener la mentalidad de que las restricciones de los clientes a menudo carecen de sentido, ya que cualquier cosa en un cliente puede ser alterada. Se requiere la validación del servidor en cada punto en el que ingresen los datos del cliente. Los atacantes confían en la ingenuidad de los desarrolladores en este único aspecto.


Las otras respuestas ya cubren lo que necesita saber. Pero quizás ayude aclarar algo más:

Hay DOS COSAS que debe hacer:

1. Validar los datos del formulario.

Como la respuesta de Jonathan Hobbs muestra muy claramente, la elección del elemento html para la entrada del formulario no hace ningún filtro confiable para usted.

La validación generalmente se realiza de una manera que no altera los datos, pero muestra el formulario de nuevo, con los campos marcados como "Corrija esto".

La mayoría de los marcos y CMS tienen constructores de formularios que lo ayudan con esta tarea. Y no solo eso, también ayudan contra CSRF (o "XSRF"), que es otra forma de ataque.

2. Sanitize / Escape variables en las declaraciones de SQL ..

.. o deja que las declaraciones preparadas hagan el trabajo por ti.

Si construye una instrucción (My) SQL con cualquier variable, proporcionada por el usuario o no, debe escapar y citar estas variables.

En general, cualquier variable que inserte en una declaración MySQL debe ser una cadena, o algo que PHP puede convertirse de manera confiable en una cadena que MySQL puede digerir. Tales como, números.

Para las cadenas, debes elegir uno de los varios métodos para escapar de la cadena, es decir, reemplazar cualquier carácter que tenga efectos secundarios en MySQL.

  • En MySQL + PHP de la vieja escuela, mysql_real_escape_string () hace el trabajo. El problema es que es demasiado fácil de olvidar, por lo que debe usar declaraciones preparadas o constructores de consultas.
  • En MySQLi, puede usar declaraciones preparadas.
  • La mayoría de los marcos y CMS proporcionan constructores de consultas que lo ayudan con esta tarea.

Si está tratando con un número, puede omitir el escape y las comillas (esta es la razón por la cual las declaraciones preparadas permiten especificar un tipo).

Es importante señalar que se escapa de las variables para la declaración de SQL, y NO para la base de datos en sí . La base de datos almacenará la cadena original, pero la instrucción necesita una versión de escape.

¿Qué pasa si omites uno de estos?

Si no usa la validación de formulario , pero desinfecta su entrada de SQL, es posible que vea todo tipo de cosas malas, ¡pero no verá la inyección de SQL! (*)

Primero, puede llevar su aplicación a un estado que no planeó. Por ejemplo, si desea calcular la edad promedio de todos los usuarios, pero un usuario dio "aljkdfaqer" para la edad, su cálculo fallará.

En segundo lugar, puede haber todo tipo de otros ataques de inyección que debe tener en cuenta: por ejemplo, la entrada del usuario podría contener javascript u otras cosas.

Todavía puede haber problemas con la base de datos: por ejemplo, si un campo (columna de la tabla de la base de datos) está limitado a 255 caracteres, y la cadena es más larga que eso. O si el campo solo acepta números, e intenta guardar una cadena no numérica en su lugar. Pero esto no es "inyección", es solo "bloquear la aplicación".

Pero, incluso si tiene un campo de texto libre donde permite cualquier entrada sin validación, aún podría guardar esto en la base de datos así si lo escapa adecuadamente cuando va a una declaración de base de datos. El problema surge cuando quieres usar esta cadena en alguna parte.

(*) o esto sería algo realmente exótico.

Si no escapa las variables para las sentencias de SQL , pero sí validó la entrada de formularios, entonces aún puede ver cosas malas sucediendo.

En primer lugar, corre el riesgo de que cuando guarde los datos en la base de datos y los cargue nuevamente, ya no serán los mismos datos, "perdidos en la traducción".

En segundo lugar, puede dar como resultado sentencias de SQL no válidas y, por lo tanto, bloquear su aplicación. Por ejemplo, si una variable contiene un carácter de comillas o comillas dobles, dependiendo de qué tipo de comillas utilice, obtendrá una declaración de MySQL no válida.

En tercer lugar, todavía puede causar inyección SQL.

Si su entrada de usuario desde formularios ya está filtrada / validada, la inyección SQl intencional puede ser menos probable, SI su entrada se reduce a una lista de opciones codificadas, o si está restringida a números. Pero cualquier entrada de texto libre se puede usar para la inyección SQL, si no se escapan adecuadamente las variables en las sentencias SQL.

E incluso si no tiene ninguna entrada de formulario, todavía podría tener cadenas de todo tipo de fuentes: leer desde el sistema de archivos, raspado de Internet, etc. Nadie puede garantizar que estas cadenas sean seguras.


Lo mejor es utilizar una consulta parametrizada para garantizar la inyección SQL. En ese caso, el aspecto de la consulta sería este:

SELECT * FROM table WHERE size = ?

Cuando proporciona una consulta como la anterior con texto que no está verificado para la integridad (la entrada no está validada en el servidor) y contiene código de inyección SQL, se manejará correctamente. En otras palabras, la solicitud dará como resultado algo así en la capa de la base de datos:

SELECT * FROM table WHERE size = ''DROP table;''

Esto simplemente seleccionará 0 resultados a medida que vuelva, lo que hará que la consulta sea ineficaz y cause daños a la base de datos sin necesidad de una lista blanca, verificación de verificación u otras técnicas. Tenga en cuenta que un programador responsable hará la seguridad en capas, y a menudo validará además de parametrizar las consultas. Sin embargo, hay muy pocas causas para no parametrizar sus consultas desde una perspectiva de rendimiento y la seguridad añadida por esta práctica es una buena razón para familiarizarse con las consultas parametrizadas.


Puede hacer algo tan simple como el siguiente ejemplo para asegurarse de que el tamaño publicado sea el esperado.

$possibleOptions = array(''All'', ''Large'', ''Medium'', ''Small''); if(in_array($_POST[''size''], $possibleOptions)) { // Expected } else { // Not Expected }

Luego use mysqli_ * si está usando una versión de php> = 5.3.0 que debe ser, para guardar su resultado. Si se usa correctamente, esto ayudará con la inyección sql.


Sí.

Cualquiera puede suplantar cualquier cosa por los valores que realmente se envían -

POR LO TANTO, para validar los menús desplegables, puede verificar que el valor con el que está trabajando esté en el menú desplegable; algo como esto sería la mejor manera (más sensatamente paranoica):

if(in_array($_POST[''ddMenu''], $dropDownValues){ $valueYouUseLaterInPDO = $dropDownValues[array_search("two", $arr)]; } else { die("effin h4x0rs! Keep off my LAMP!!"); }


Su navegador web no "sabe" que está recibiendo una página de php, todo lo que ve es html. Y la capa http sabe incluso menos que eso. Debe poder manejar casi cualquier tipo de entrada que pueda cruzar la capa http (afortunadamente para la mayoría de las entradas, php ya dará un error). Si intenta evitar que las solicitudes maliciosas arruinen su base de datos, debe suponer que el tipo que está al otro lado sabe lo que hace, y que no está limitado a lo que puede ver en su navegador en circunstancias normales ( sin mencionar lo que puedes jugar con las herramientas de desarrollo de un navegador). Entonces, sí, debe atender cualquier entrada de su menú desplegable, pero para la mayoría de las entradas puede dar un error.


Todo lo que se envía desde su formulario llega a su servidor como texto a través de los cables. No hay nada que impida que alguien cree un bot para imitar al cliente o escribirlo desde un terminal si así lo desean. Nunca asuma que, debido a que programó el cliente, actuará como usted cree que sucederá. Esto es realmente fácil de burlar.

Example de lo que puede ocurrir y sucederá cuando confíes en el cliente.


Un pirata informático puede omitir completamente el navegador, incluida la verificación de formularios de Javascript, enviando una solicitud utilizando Telnet. Por supuesto, mirará el código de su página html para obtener los nombres de campo que tiene que usar, pero a partir de ese momento, ''todo vale'' para él. Por lo tanto, debe verificar todos los valores enviados en el servidor como si no provinieran de su página html.


Una forma de protegerse de que los usuarios cambien los menús desplegables utilizando la consola es usar valores enteros en ellos. Luego puede validar que el valor POST contiene un número entero y usar una matriz para convertirlo en texto cuando sea necesario. P.ej:

<?php // No, you don''t need to specify the numbers in the array but as we''re using them I always find having them visually there helpful. $sizes = array(0 => ''All'', 1 => ''Large'', 2 => ''Medium'', 3 => ''Small''); $size = filter_input(INPUT_POST, "size", FILTER_VALIDATE_INT); echo ''<select name="size">''; foreach($sizes as $i => $s) { echo ''<option value="'' . $i . ''"'' . ($i == $size ? '' selected'' : '''') . ''>'' . $s . ''</option>''; } echo ''</select>'';

Luego puede usar $size en su consulta, sabiendo que solo contendrá FALSE o un número entero.