[PHP] Prevenir inyección SQL en sentencias

  • 8 Respuestas
  • 1980 Vistas

Valarjar
Hijo de Odyn

[PHP] Prevenir inyección SQL en sentencias
« en: Mayo 26, 2017, 17:13:59 pm »
¿Cómo se previenen?

Utilizando instrucciones preparadas y consultas parametizadas. Estas son sentencias SQL que son enviadas y analizadas por el servidor de la base de datos separadamente de cualquier parámetro. De esta manera es imposible para un atacante inyectar SQL malicioso.


¿Cómo se utilizan?

Usando la extensión MySQLi o PDO y ciertos parámetros que utilizaremos a continuación, en este caso (como yo lo utilizo) voy a poner el ejemplo en MySQLi.

Código

Previamente a empezar con las sentencias, necesitamos crear nuestra conexión con la base de datos, en este caso llamado conexion.php

conexion.php
Código: PHP
  1. <?php
  2. ##########################
  3. $hostname = "servidor";
  4. $username = "usuario db";
  5. $password = "contraseña db";
  6. $database = "base de datos";
  7. ##########################
  8.  
  9. $conexion = new mysqli($hostname, $username, $password, $database);
  10.  
  11. /* comprobar conexión */
  12. if ($conexion->connect_error) {
  13.     die('Error de Conexión (' . $conexion->connect_errno . ') '
  14.             . $conexion->connect_error);
  15. }
  16.  

Una vez creada la conexión, podemos prevenir nuestras inyeciones usando sentencias parametizadas como en este ejemplo.

Código: PHP
  1. //Incluimos el anterior código php para poder establecer una conexión con la base de datos. Include_once significa que solo se incluya una vez, para que no se vuelva establecer más veces llevando a errores.
  2. include_once('conexion.php');
  3.  
  4. //En caso que enviemos mediante post un usuario establecemos variable para prepararla después.
  5. $nombre = $_POST['nombredelinput'];
  6.  
  7. //Primero creamos la sentencia SQL
  8. $sql = "SELECT * FROM usuarios WHERE nombre = ?";
  9.  
  10. //Preparamos la sentencia anteriormente establecida
  11. $stmt = $conexión->prepare($sql); //$conexion es una variable previamente creada para conectarnos a nuestra db.
  12.  
  13. //Enlazamos el parámetro a la sentencia. La "s" significa "string", en caso de tener un número sería "i". Opciones : i = integer, d = double, s = string, b = blob.
  14. $stmt->bind_param('s', $nombre);
  15.  
  16. //Ejecutamos
  17. $stmt->execute();
  18.  
  19. //Obtenemos resultado
  20. $resultado = $stmt->get_result();
  21.  
  22. //Mientras que haya resultado de filas hacer algo con $row.
  23. while ($row = $result->fetch_assoc()) {
  24.     // Hacer algo con $row.
  25. }
  26.  
  27. //Y para acabar, liberamos memoria resultados en memoria y cerramos la consulta con close.
  28. $stmt->free_result();
  29. $stmt->close();
  30.  
« Última modificación: Mayo 27, 2017, 06:51:37 am por Valarjar »

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #1 en: Mayo 26, 2017, 23:55:48 pm »
No uses MySQLi, esta ya anticuado y seguramente lo deprecaran en breve.

Para evitar inyeccion SQL y otras marranadas es mejor usar los filtros: (http://php.net/manual/es/function.filter-input.php)
Código: PHP
  1. $variable = filter_input(INPUT_POST, 'variable_del_post');
  2.  

Aunque yo prefiero filtrar todo el POST directamente:
Código: PHP
  1. $post = filter_input_array(INPUT_POST);
  2.  

Ten cuidado si buscas cosas por internet que ya hay verdaderos tutoriales con codigo ancient de antes de cristo. Hace tiempo hice un post en mi blog hablando de ello.

Valarjar
Hijo de Odyn

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #2 en: Mayo 27, 2017, 05:03:34 am »
No uses MySQLi, esta ya anticuado y seguramente lo deprecaran en breve.

Para evitar inyeccion SQL y otras marranadas es mejor usar los filtros: (http://php.net/manual/es/function.filter-input.php)
Código: PHP
  1. $variable = filter_input(INPUT_POST, 'variable_del_post');
  2.  

Aunque yo prefiero filtrar todo el POST directamente:
Código: PHP
  1. $post = filter_input_array(INPUT_POST);
  2.  

Ten cuidado si buscas cosas por internet que ya hay verdaderos tutoriales con codigo ancient de antes de cristo. Hace tiempo hice un post en mi blog hablando de ello.

No estoy de acuerdo. Dudo, pero muchísimo que mysqli lo hagan deprecated en breve. PDO la única ventaja a parte de names en parametizadas es que soporta múltiples interfaces de bases de datos. Si utilizas MySQL en tus proyectos, es una tontería usar PDO y no usar funciones nativas ya que pierdes rendimiento. El propio facebook utiliza MySQL Async.

No es necesario utilizar filters si se usa prepared statements para evitar inyección, aunque lo utilizo cuando quiero validar un input, por ejemplo, un email, número etc, y si no es correcto devuelve error, aunque lo hayas prevenido en la parte cliente en html/javascript y cualquier usuario intente saltarlo.

El WP que utilizas en tus proyectos, utiliza MySQLi.

Y respecto que cuidado con lo que busco.... es lo que utilizo de base en mis proyectos (aunque el que está puesto es muy básico para que se coja el concepto del las funciones preparadas, sin crear clases ni objetos, esto va enfocado para usuarios nuevos), y si en alguna ocasión me falta conocimiento, siempre busco lo más actualizado.

¿Cómo sería según tu criterio, el código que he puesto "actualizado"?

Saludos.
« Última modificación: Mayo 27, 2017, 14:15:37 pm por Valarjar »

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #3 en: Mayo 28, 2017, 00:01:56 am »
Yo uso PDO por muchas razones y todas las dices tu. Soporta multiples rdbms y las names parametrizadas. Aunque muchas veces se que voy a usar MySQL, me he encontrado mas de una vez que el servidor de produccion no lo es y no avisan. Entonces con PDO cambias 1 linea y con mysqli te jodes :) (que es lo que me paso a mi la primera vez que me encontre una situacion asi).

Lo del rendimiento, pues mira, si y no. Si porque es nativo y no porque las secuencias de escape (para validar las sentencias y que no inyecten codigo, etc) las hace contra el servidor y PDO no, las hace en el lado cliente.

https://wooptoo.com/blog/pdo-vs-mysqli-performance-comparison/

Mas cosas; no metas a Facebook en esto. Muchos se orgullecen de que Facebook usara PHP contra MySQL. Pero nada mas lejos de la realidad. Hace ya años que se liaron a compilar PHP con Hiphop y la version de MySQL que usan no es publica, este rdbms era Open Source y ellos mismos hicieron sus "arreglillos".

Referente a WP, pues es su problema si usan msqli, la verdad es que es un codigo muy antiguo que se inicio con desarrollo procedural (es una copia de un blog llamado b2 cafelog) y que ha ido evolucionando. Han conseguido crear algunas clases y encapsular el codigo de funciones en ellas (como la wpdb) pero eso no quita que si te lias a mirar las tripas alucines de lo mal hecho que esta.

Pues eso ... que tengo sueño :/

Valarjar
Hijo de Odyn

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #4 en: Mayo 28, 2017, 19:39:37 pm »
Yo uso PDO por muchas razones y todas las dices tu. Soporta multiples rdbms y las names parametrizadas. Aunque muchas veces se que voy a usar MySQL, me he encontrado mas de una vez que el servidor de produccion no lo es y no avisan. Entonces con PDO cambias 1 linea y con mysqli te jodes :) (que es lo que me paso a mi la primera vez que me encontre una situacion asi).

Lo del rendimiento, pues mira, si y no. Si porque es nativo y no porque las secuencias de escape (para validar las sentencias y que no inyecten codigo, etc) las hace contra el servidor y PDO no, las hace en el lado cliente.

https://wooptoo.com/blog/pdo-vs-mysqli-performance-comparison/

Mas cosas; no metas a Facebook en esto. Muchos se orgullecen de que Facebook usara PHP contra MySQL. Pero nada mas lejos de la realidad. Hace ya años que se liaron a compilar PHP con Hiphop y la version de MySQL que usan no es publica, este rdbms era Open Source y ellos mismos hicieron sus "arreglillos".

Referente a WP, pues es su problema si usan msqli, la verdad es que es un codigo muy antiguo que se inicio con desarrollo procedural (es una copia de un blog llamado b2 cafelog) y que ha ido evolucionando. Han conseguido crear algunas clases y encapsular el codigo de funciones en ellas (como la wpdb) pero eso no quita que si te lias a mirar las tripas alucines de lo mal hecho que esta.

Pues eso ... que tengo sueño :/

Podíamos hacer unos manuales en PDO y Hack con HHVM.

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #5 en: Mayo 28, 2017, 21:04:05 pm »
No he usado nunca hhvm, no por nada, sino porque no me ha salido la oportunidad.

Pero todo es ponerse :)
Pongamosnos

Valarjar
Hijo de Odyn

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #6 en: Mayo 28, 2017, 23:49:20 pm »
No he usado nunca hhvm, no por nada, sino porque no me ha salido la oportunidad.

Pero todo es ponerse :)
Pongamosnos

Yo tampoco, y ya me llamó la atención hace tiempo, creo que es una buena oportunidad, no solo para los usuarios del foro si no para aprender nosotros mismos también jeje, y tampoco hay mucho material con ello por los foros.

Voy a crear una categoría específica para ello.

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #7 en: Mayo 29, 2017, 00:02:45 am »
Miro de hacer el tuto

Os interesa docker tambien?

Valarjar
Hijo de Odyn

Re:[PHP] Prevenir inyección SQL en sentencias
« Respuesta #8 en: Mayo 29, 2017, 00:10:14 am »
Miro de hacer el tuto

Os interesa docker tambien?

Todo lo que sea para aprender y tener nuevos conocimientos, bienvenido sea. La verdad es que nunca lo he usado pero sí he escuchado hablar de ella.

Por cierto , ya que he creado el foro:

https://valarjar.com/hack/