Diferencia entre revisiones de «SQL Injection»

De FdIwiki ELP
Saltar a: navegación, buscar
m
Línea 61: Línea 61:
 
== Prevención ==
 
== Prevención ==
  
 
== Casos Famosos ==
 
  
  
 
== Referencias y enlaces externos ==
 
== Referencias y enlaces externos ==

Revisión de 13:34 26 ene 2017

SQL Injection, o una inyección SQL, es un ataque en el cual se manipula y se "inyecta" comandos SQL en una sentencia SQL preestablecida mediante una entrada de usuario (de ahí el nombre). Usualmente esto se puede hacer ya que las entradas que se reciben de parte de los usuarios no han sido desinfectadas (sanitize en inglés) y un usuario malicioso aprovecha esta vulnerabilidad para introducir su código, a fin de alterar el funcionamiento normal del programa y robar, modificar o eliminar información, e inclusive ganar acceso a acciones que sólo debería de tener un administrador de la BDD, como modificar su estructura, apagar la base de datos, etc.

Una inyección SQL es considerado un ataque por la (Open Web Application Security Project), y por ende, puede ser penalizado como cualquier otro delito informático que infrinja contra las leyes establecidas.


Exploits of a mom.png

Imagen cortesía de xkcd

Ejemplo

Para entender lo que es una inyección SQL, lo mejor es visualizarlo con un ejemplo en código. Se utilizará Python para explicar el siguiente ejemplo.

Imaginemos un caso típico en el que un usuario quiere iniciar sesión en una aplicación web. Este usuario sólo debe introducir su nombre de usuario y su contraseña para poder acceder a ella. Entonces, la aplicación web podría recibir el usuario y contraseña a través de una solicitud POST de la siguiente manera:


def login():
    username = request.forms['username'] # username = 'one_user'
    password = request.forms['password'] # password = 'one_password'

Ahora, imaginemos que tenemos declarada una sentencia SQL como la siguiente:

    query = "SELECT id FROM Users WHERE username = '{0}' AND password = '{1}'"

Un desarrollador simplemente podría dar formato a esta sentencia añadiendo las variables username y password de la siguiente manera:

    query = query.format(username, password)

Y el resultado sería que ahora el valor de query cambia a:

    # query = "SELECT id FROM Users WHERE username = 'one_user' AND password = 'one_password'"

Con esto, si se tiene un buen usuario que ha introducido su nombre de usuario y su contraseña correcta, esta consulta regresaría su id correspondiente y se podría acceder a los servicios que ofrece la aplicación sin ningún problema. Pero que pasa si nuestro usuario no es un buen usuario, sino que es un usuario malicioso y nos da las siguientes entradas:

def login():
    username = request.forms['username'] # username = 'hacked'
    password = request.forms['password'] # password = 'hacked' OR '1'='1'-- '

Al dar formato a la sentencia SQL anteriormente descrita, ésta quedaría de la siguiente forma:

    # query = "SELECT id FROM Users WHERE username = 'hacked' AND password = 'hacked' OR '1'='1'--'"
    # La última comilla simple quedaría comentada por "--" y no causaría ningún problema de sintaxis

Recordando un poco de álgebra booleana, el AND tiene precedencia sobre el OR. De este modo, la condición sería WHERE (username = 'hacked' AND password = 'hacked') OR '1'='1'. La primera parte de la cláusula WHERE no nos importa ya que sabemos que la segunda parte siempre va a ser True. Así que con esto, la consulta regresaría todos los id's de usuarios que existen en la base de datos. Si un usuario malicioso llega a coger estos id's, podría hacerse pasar por algún usuario válido en la aplicación web y actuar a gusto.

Prevención

Referencias y enlaces externos