lunes, 21 de junio de 2010

Inyección SQL




La inyección SQL es un agujero de seguridad en la informática que se puede producir al ejecutar una sentencia en una base datos con datos entrados por usuarios mal intencionados o por error en algunos casos. La inyección se produce cuando el programador no filtra de forma correcta los datos para evitar la posible inyección.
El nombre de inyección viene dado por la forma en que se introduce el código mal intencionado en el código correcto.
El ejemplo clásico es una sentencia para verificar una autenticación de usuario.
Tenemos en la base de datos de nuestro sistema una tabla llamada usuario, que contiene el nombre del usuario, el correo electrónico, la contraseña, entre otros datos.
Para verificar los datos de un usuario, se utilizaría la siguiente sentencia SQL:



Select count(*) from usuario where nombre_usuario = 'dato_usuario' and contrasena = 'dato_pass'


Lo que se hace en esta sentencia es contar los usuarios que tengan el mismo nombre de usuario entrado (dato_usuario) y la contraseña entrada (dato_pass). Normalmente un resultado positivo daría como resultado una cantidad igual 1 si los datos coinciden y 0 si el usuario o la contraseña entrada están mal.
Por ejemplo:


Select count(*) from usuario where nombre_usuario = 'pepe' and contrasena = '12345'



Sin embargo si el programador no valida que el valor: dato_usuario y : dato_pass , no contengan datos maliciosos podría ocurrir lo siguiente:

Select count(*) from usuario where nombre_usuario = 'pepe' and contrasena = ' cualquier_cosa' or 'h' = 'h '

En este caso sea cual sea el nombre de usuario que se entre el resultado sería una cantidad mayor que 0 y por lo tanto lograría tener acceso sin la contraseña correcta al un servicio que se esté programando. La razón es que en vez de entrar una contraseña, se inyectó un código malicioso al código SQL original para alterar su funcionamiento correcto.

Fíjense que se altera el funcionamiento porque se introdujo: cualquier_cosa' or 'h' = 'h en vez de una contraseña , si lo dividimos por partes veremos que cualquier_cosa' cierra la contraseña y luego viene un operador OR lo que implica que si después del OR la operación da como resultado Verdadero toda la operación es verdadera ya que (false OR true) = true. Después del OR viene 'h'='h que se cierra con la última comilla, quedando 'h'='h' y es evidente que 'h' es igual 'h'.

Este ejemplo no es de los más trágicos pues igualmente se pueden ejecutar sentencia que borren todos los registros de la base de datos, lo cual podría provocar un serio problema en cualquier sistema.


¿Cómo evitar las Inyecciones SQL?

Evidentemente para evitar este problema simplemente hay que filtrar los datos externos que entremos en la sentencia SQL. En dependencia del sistema gestor de base datos y el lenguaje de programación existen muchas formas de evitar el problema.


Si usamos PHP - MYSQL

Si usamos el gestor de bases de datos lo que debemos hacer es eliminar las comillas. Explicaré a continuación como evitar el ataque usando lenguaje de programación PHP .


  1. No permitir comillas en casos de datos como un nombre de usuario, el cual solo debería aceptar caracteres alfanuméricos. Esto sin duda evitaría este problema sin mayores contratiempos con un simple filtro.

  2. Escapar todas las comillas de un texto determinado. Escapar no es más que colocar o anteponer el carácter “\” antes de poner una comilla, el carácter “\” indica que luego viene un carácter especial, evitando que este carácter tenga una interpretación errónea. Si sabemos en MYSQL el carácter Comilla tiene un significado especial , evitamos este significado al anteponer: “\”. Usted podría programar su propia función para realizar este filtro , sin embargo ya existen funciones en PHP que ejecutan esta tarea de manera eficiente. Lo ideal es usar la función mysql_real_escape_string.

  3. Entonces el ejmplo inicial quedaría de la siquiente forma:


    $pass = mysql_real_escape_string($pass);

    $query = “Select count(*) from usuario where nombre_usuario = ‘pepe’ and contrasena = ‘$pass’ “;


  4. La función mysql_real_escape_string está disponible en versiones superiores de PHP , no en las versiones antiguas 3 y 4. Por lo tanto es posible que tenga que usar otras formas de escapar los datos. Por ejemplo:


  5. $valor = str_replace(“’”, “\’” ,$valor); // lo que hacemos es reemplazar todas las comillas simples por \’.


  6. La función addslashes , también puede ser usada directamente para adicionar barra invertida a los caracteres comilla simple ('), comilla doble ("), barra invertida (\) y valor NULL. La función contraria a esta es stripslashes , la cual elimina las barras invertidas dejando la cadena como mismo estaba al inicio.


  7. Magic quotes , es una forma de evitar inyección SQL en PHP , la cual no recomiendo yo como programador ni prácticamente nadie en ningún artículo de los que he leído. Esta es una opción que puede habilitarse en la configuración de PHP (magic_quotes_gpc=on) y que en versiones antiguas venía habilitado por defecto. Lo que hace esta opción es aplicar el escape de las comillas en todos los datos que vienen por las variables: $_GET, $_REQUEST, $_POST and $_COOKIE de forma automática. Sin duda fue una solución muy exagerada y que trajo consigo que fue peor el remedio que la enfermedad. Si me preguntan el por qué:

    - Hay muchos muchísimos datos que usamos en nuestras aplicaciones que no intentan poner una inyección SQL. Por ejemplo cuando almacena código HTML , el cual contiene comillas que no necesariamente traen problemas en la base de datos.

    - Esto no resuelve ningún problema en gestores de base datos que tienen otras vulnerabilidades que no son precisamente las comillas.



    Nota: Es muy importante tener presente que si tenemos en uso esta opción a su conveniencia como programador, debe tener cuidado de no usar las funciones addslashes , ya que entonces obtendría una cadena con doble escape. La forma de saber esto de forma automática e independiente de la configuración PHP que tenga un servidor u otro es consultando la función get_magic_quotes_gpc() , si da como resultado 1 es que Magic quotes está activada.



    Luego si queremos recuperar estos valores de la base de datos y que se restablezcan a su estado original con las comillas podemos usar la ya mencionada función: stripslashes , que como su nombre lo indica elimina las barras invertidas.





No dude nunca en detenerse y analizar en su proyecto que método de seguridad va usar para evitar este tipo de ataque. La Inyección SQL es un ataque prevenible y que a veces se olvida tener en cuenta.

Moisés Soft , le responderá cualquier duda que tenga acerca de Inyección SQL. No dude en contactarnos

No hay comentarios:

Publicar un comentario