La inyección de SQL puede omitir el inicio de sesión pero no soltar la tabla

14

He configurado un entorno de prueba para ejecutar algo de inyección de SQL en mi código y aprender a defenderme de él. Puedo omitir el formulario de inicio de sesión usando lo siguiente en el campo de contraseña:

' OR username = 'admin

Lo que me da la consulta:

SELECT * FROM customer_data WHERE username = '' AND password = '' OR username = 'admin'

Esto funciona bien, pero estoy teniendo problemas para dejar caer una mesa. He intentado varios intentos de insertar algo como esto en el campo de contraseña:

OR '1' = '1'; DROP TABLE temp; --

Creé una tabla llamada temp solo para probarla, pero nada de lo que puedo pensar ha funcionado. Si inicio sesión en PHP MyAdmin (las mismas credenciales que usa la página) puedo insertar manualmente la consulta que se construiría arriba y funciona bien.

    
pregunta Scott Helme 22.07.2013 - 09:21
fuente

3 respuestas

34

Respondiendo a su pregunta

mysql_query() no admite consultas múltiples como se documenta:

  

mysql_query () envía una consulta única (no se admiten varias consultas) a la base de datos activa actualmente en el servidor que está asociado con el identificador de enlace especificado.

Lo que significa que DROP TABLE temp; -- nunca se ejecuta.
Aunque es posible si usa mysqli::multi_query o si usa PDO .

Mejores prácticas

¿Advertencia?
¿Ves ese gran cuadro rojo advertencia ? La extensión mysql está en proceso de desaprobación y emitirá advertencias a partir de PHP 5.5.0. Incluso hay planes para dejarlo completamente en PHP 5.6 o PHP 6.0 source . Tenga en cuenta que mysql_ no se rompe, como afirmó Ángel González:

  

La extensión no está rota. El problema es el mal uso. Se puede usar de forma segura, y los buenos desarrolladores lo han estado haciendo durante años, creando envoltorios de php. En citas mágicas, el trabajo ha sido todo lo contrario. Los desarrolladores habían estado detectando la función en php y desactivándola .

El nuevo estándar
El nuevo estándar es MySQLi o PDO . No compararé las dos extensiones aquí, pero realmente hay un montón de buenas características, especialmente de PHP 5.3+, que le ahorrarán tiempo y esfuerzos. Tenga en cuenta que al utilizar MySQLi / PDO no lo protegerá per se de las inyecciones de SQL. La mejor opción sería utilizar declaraciones preparadas . Los datos se envían por separado de la consulta, por lo que es imposible inyectar valores. Esto está bien explicado por Anthony Ferrara en este video .

Ten cuidado
Pero espera "imposible"? Eso suena demasiado bien :)
Digamos, por ejemplo, que tenemos dos grupos: group1 & Grupo 2. Hay un cierto archivo php deleteUser.php que obtiene un ID de $_GET .
La declaración preparada tiene este aspecto: DELETE FROM users WHERE id = ? . Cuando la consulta se realice con $_GET['id'] , el usuario con ID = $_GET['id'] se eliminará. Oye, pero eso significa que los usuarios del grupo 1 podrían eliminar a los usuarios del grupo 2 utilizando ese ID que no está destinado. Así que podemos editar la consulta en algo como DELETE FROM users WHERE id = ? AND group = ? y enviar el nombre del grupo del usuario que está junto con la consulta.
En pocas palabras: las declaraciones preparadas no lo protegerán de las fallas lógicas.

¿Consulta múltiple?
No necesitas consultas múltiples. Si desea hacer dos cosas, entonces hágalo por separado, le dará más control sobre sus consultas y hará que su código sea más legible.

En otra nota:
Si está creando y eliminando tablas dinámicamente, lo más probable es que lo haga mal. Debe diseñar su base de datos de tal manera que esto no sea necesario. Por supuesto, puede haber excepciones, pero en su mayoría están bloqueadas, ya que puede buscar una solución NoSQL (otro motor de db).

TL;DR

  • Deje de usar las funciones mysql_ y diríjase a MySQLi o DOP
  • Use declaraciones preparadas, tenga en cuenta que no lo protegerá de ataques si no asegura la lógica detrás de él
  • No utilizar consultas múltiples
  • Haz un buen diseño de base de datos
  • Si desea entrenar sus habilidades de piratería, puede marcar ¿Sistemas operativos vulnerables?
respondido por el HamZa 22.07.2013 - 13:27
fuente
10

Puede ser que la función que utiliza en PHP no permita consultas apiladas o porque el usuario que está configurado para realizar las consultas no tiene privilegios para eliminar la tabla. Le sugiero que registre todos los resultados y excepciones lanzados por la aplicación. Podría dar una pista de dónde radica su problema.

EDIT 1: En lugar de ejecutar la consulta, imprímela en la pantalla.

    
respondido por el Lucas Kauffman 22.07.2013 - 09:26
fuente
4

¡Esto fue un descuido de mi parte después de una lectura nocturna de la documentación!

  

mysql_query () envía una consulta única (no se admiten varias consultas) a la base de datos activa actualmente en el servidor que está asociado con el identificador de enlace especificado.

    
respondido por el Scott Helme 22.07.2013 - 10:02
fuente

Lea otras preguntas en las etiquetas