Joven hacker sonriendo

¿Cómo evitar que entren a mis datos?

Una base de datos es un software capaz de organizar información con el objetivo que un computador pueda seleccionar de una forma rápida los elementos que necesite.

Generalmente, las bases de datos se organizan por campos, registros y archivos. Un campo es una pieza única de información; un registro es un sistema completo de campos; y un archivo es una colección de registros. Por ejemplo, una libreta de direcciones es análoga a un archivo. Contiene una lista de registros, cada uno de los cuales consiste en tres campos: nombre, dirección, y número de teléfono.

Las bases de datos son herramientas que recopilan y organizan la información, estas pueden almacenar datos de personas, productos, precios o datos más sensibles como direcciones de nuestros clientes, tarjetas de crédito y sus contraseñas. Teniendo esto en mente el tema a tratar es la inyección SQL.

footnote
Figura 1. Bases de datos
[Imagen tomada de Tecniplanet]

¿Qué es una inyección SQL?

Un ataque por inyección SQL como su nombre lo indica consiste en la “inyección” de una consulta SQL por medio de los datos desde el cliente hacia un servidor. Como dijimos anteriormente una base de datos puede contener información sensible de un usuario y un ataque exitoso puede indicarle al servidor que revele esta información a un atacante o no solo revelarla, podría editar, insertar o eliminar datos.

La inyección SQL es común en aplicaciones PHP y ASP esto debido a interfaces con funcionalidades obsoletas, la gravedad de un ataque depende en gran medida de la creatividad del atacante y en menor medida a las contramedidas tomadas para repeler el ataque.

¿Cómo explotar estas características?

Este tipo de ataque se puede realizar de dos formas, ya sea desde un campo de formulario o desde una URL y puede realizar varias acciones, desde un ingreso por contraseña, hasta revelar información

¿Cómo ingresar por medio de un ataque?

En este ejemplo vamos por medio de un ataque de inyección SQL ingresar a un usuario:

inyeccion-form
Figura 2. Inyección a un formulario

Qué paso

El código usado para realizar este ingreso sin tener acceso a su contraseña es (Or 1 = 1) y lo que le está indicando; a la base de datos es básicamente una sentencia que siempre es verdadera el problema para la explotación de este ataque Blind SQL injection es que realiza:: la búsqueda de usuarios carácter por carácter así, por ejemplo, si la contraseña es Hola el código ingresado testea letra por letra y acumula en caso:: de un resultado positivo de esta manera va guardando la H luego la o hasta dar con la palabra completa.

Otro tipo de ataque puede darse por inyección en las URL mostrado a continuación:

inyeccion-url
Figura 3. Inyección a una URL

El código a usar es (’UNION ALL SELECT username, password FROM members WHERE admin=1--) Como se puede observar es una petición pidiendo al servidor que revele quienes tienen el estatus de administrador en otras palabras “administrador=1”. Directamente el servidor interpreta que debe mostrar al(los) usuario(s) que son administradores, pero además del usuario necesitamos la contraseña que se puede obtener de la siguiente manera:

clave
Figura 4. Buscando la clave del administrador

El código a usar es similar al de detectar al administrador (’UNION ALL SELECT password, 2 FROM members WHERE username=’bellamond’--); al igual que el anterior es simplemente indicarle al servidor que me muestre la contraseña del administrador para lograr entrar a su cuenta, aunque la contraseña:: este en SHA1 lo grave es que el servidor permitió ver la contraseña de un administrador

¿Cómo evitar este tipo de ataque?

El principal punto débil de estos ataques es que si dejamos que un usuario ingrese cualquier tipo de carácter sin control -para realizar el ataque usamos comilla sencilla- un atacante podría aprovecharse de las comillas para declarar cadenas de texto que interpreta un servidor.

Por lo tanto, la solución estándar para evitar que un atacante realice una consulta es transformarlas comillas antes de que ingresen al servidor por ejemplo una comilla doble debe transformarse a (\”) y así el servidor interpretara esto como una comilla doble y no como una solicitud para iniciar una consulta, para hacer esto se programa según el lenguaje.

En Perl

El método quote filtra los caracteres especiales -Esto asumiendo que una variable $sql hace referencia a un objeto DBI-

test.py
1
2
3
4
5
6
$query = $sql->prepare
   (
         "SELECT * FROM usuarios WHERE nombre = "
     .
         $sql->quote($nombre_usuario)
    );

En PHP

La manera más utilizada para evitar este ataque si se está usando MYSQL es con la función mysql_real_escape_string la cual coloca barras invertidas ante los siguientes caracteres: \x00 \n \r \' \" y \x1a. Con lo cual garantiza que los datos sean seguros antes de enviar una consulta a MySQL.

1
2
3
4
5
6
7
8
<?php
$enlace = mysql_connect('mysql_host', 'mysql_usuario', 'mysql_contrasenya')
    OR die(mysql_error());
$query = sprintf("SELECT * FROM usuarios WHERE usuario='%s' AND
     password='%s'",
            mysql_real_escape_string($usuario),
            mysql_real_escape_string($password));
?>

Y en caso de usar MySQLi

1
2
3
4
$conexion = mysqli_connect("host", "usuario", "clave", "bdd");
$query = mysqli_query($conexion, "SELECT * FROM usuarios WHERE nombre = '" . mysqli_real_escape_string($conexion, $nombre) . "'");
$query = $this->query("SELECT * FROM usuarios WHERE nombre = '" . $this->real_escape_string( $nombre ) . "'");
$query = $this->mysqli->query("SELECT * FROM usuarios WHERE nombre = '" . $this->mysqli->real_escape_string($nombre) . "'");

Sin embargo, se recomienda utilizar P.D.O. (PHP Data Object) que ya ofrecen consultas preparadas.

1
2
3
4
$statement = $pdo->prepare("SELECT * FROM usuarios WHERE nombre = :nombre");
$statement->bindParam(':nombre', $nombre_usuario);
$statement->execute();
$result = $statement->fetch();

Ruby on Rails (RoR)

En RoR, las consultas son verificadas automáticamente por cualquiera de los métodos de búsqueda incluidos.

1
Project.find consulta := "SELECT * FROM usuarios WHERE nombre = '" + nombreUsuario + "';"

Estos ataques se pueden evitar en muchos lenguajes distintos, e incluso hay lenguajes que por defecto aumenta la dificultad al atacante para explotar esta vulnerabilidad, pero lo que se debe tener en cuenta es que donde hay una consulta SQL existe una vulnerabilidad a nuestro sistema.

Referencia


Foto del autor

Francisco Bernal Baquero

Ingeniero Electrónico.

Programador en Python y Ruby, siempre dispuesto a aprender.


Relacionado





Haz un comentario