SQL Injection en MySQL ¿Qué es y cómo evitarlo?

Cuando hablé sobre los ataques de Black Hat SEO, os conté muy por encima que es un ataque por SQL Injection. Pues hoy vamos a ver una forma de evitarlos.

¿Qué es un ataque por Inyección SQL?
Con un ataque de este tipo lo que intentan es conseguir la información que almacenamos en nuestra base de datos, modificarla o incluso eliminarla. Para ello localizan archivos a los que les pasamos variables a través de GET o POST.

Vamos a ver un ejemplo, si tenemos un archivo con una query de este estilo:

&query='DELETE * FROM noticias WHERE id="'.$_GET['id'].'"';

En un archivo llamado noticias.php y le pasamos el parámetro id por la url (get), podrán atacarnos llamando al archivo y modificando los parámetros a pasarle:

noticias.php?id=12" OR 1="1

Si volvemos a la query, veremos que con los nuevos parámetros, esta quedaría así:

&query='DELETE * FROM noticias WHERE id="12" OR 1="1"';

Por lo que modificarían nuestra query, haciéndola siempre posible, pues 1 es igual a 1, por lo tanto eliminaría todas las noticias de nuestra tabla, cuando nosotros lo que queríamos era eliminar una única noticia.

En el caso de pasar las variables por POST también sería posible el ataque, pues añadirían el código malicioso en un campo del formulario dando el mismo resultado.

¿Cómo evitamos un ataque de este tipo?
Cómo no queremos que nos arruinen de por vida, vamos a utilizar dos funciones php muy útiles: sprintf y mysql_real_escape_string. Si las aplicamos a nuestra query, quedaría así:

$query = sprintf("DELETE * FROM noticias WHERE id='%d'",mysql_real_escape_string($id));

Con sprintf damos formato a nuestra sentencia asignando el espacio justo para los parámetros a recoger (%d para un número, %s para una cadena, etc) y con mysql_real_escape_string escapamos caracteres especiales, por lo que si nos hicieran el mismo ataque (12″ OR 1=”1) nos devolvería esto:

&query='DELETE * FROM noticias WHERE id="12"';

Cómo véis sólo permanece el 12, eliminando el trozo ” OR 1=”1 y evitando así que la consulta siempre sea posible.

Porque más vale prevenir que curar :P

  • 21 enero 2010
  • Programación
  • ,

11 comments on “SQL Injection en MySQL ¿Qué es y cómo evitarlo?”

  1. A partir de la versión 5 y creo que a partir de la 4.X de MySQL este problema ya está resuelto y no es necesario ningún tipo de protección extra. De todas formas el bug de MySQL también afecta a PHPMyAdmin con lo que tendrían acceso a todas las bases de datos que tuvieses ahí creadas, la liada sería mucho mayor.

    Esta forma de reventar bases de datos ya está en desuso y tan solo se enseña a modo anecdotico en bases de datos para saber que se puede hacer si no se usa con cuidado, si sabes ocultar bien el código no tienen porque hacer daño a tu base de datos.

    Un saludo!!

  2. Gracias por tu comentario Alex!

    javierh yo tengo entendido que no está en desuso, al contrario, que es bastante utilizado para ataques de black hat seo.. aunque ya me dejas en duda, voy a tener que investigar un poquito más.. gracias por el dato!

  3. Pingback: Bitacoras.com
  4. Bueno,queria comentarte que te olvidastes de una cosa;

    Tambien para evitar una SQLi,se puede poner:

    $id = @int()$_GET[‘id’];

    o

    $id = @strip_tags($_GET[‘id’]);

    PD: Tengo 16 años. :)

  5. Hola!
    Recientemente en menos de un mes me han volteado una base de datos con stored procedure y dejan inactiva la base y cuando quiero crear o correr uno nuevo me muestra esto:

    MySQL ha dicho: #1548 – Cannot load from mysql.proc. The table is probably corrupted

    Sólo me lo han solucionado desde el hosting pero la verdad que es molesto.
    Cómo puedo evitar que ataquen las rutinas y quede inoperable la BD?
    Grax.

  6. Definitivamente la entrada tiene todo lo que se requiere para prevenir lo “básico”. Legible, conciso, elegante. Felicidades!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *