SQL Injection - Que es, como hacerlo, como evitarlo


Cuando estudiaba en la universidad traté incontables veces de investigar sobre el tema. Siempre me encontré con el poderoso firewall institucional que me bloqueaba las búsquedas. Pasaron años antes de saber lo suficiente. Mi ignorancia me hizo víctima, ya que todos mis proyectos iniciales carecían de la debida protección.

Cuando por fin tube los suficientes conocimientos al respecto, me dí a la tarea de hacer unas cuantas pruebas con mis propios sistemas y, para mi sorpresa, no estaba protegido. Hasta ese momento, nunca había desarrollado un sistema que manejara información delicada, sin embargo, si aspiraba atraer proyectos grandes e importantes, debía poder garantizar a mis clientes la integridad de sus datos. Evitar SQL Injection tendría que ser el primer paso para lograrlo.

¿Que es SQL Injection?


Inyección SQL es un método de infiltración de código intruso que se vale de una vulnerabilidad informática presente en una aplicación en el nivel de validación de las entradas para realizar operaciones sobre una base de datos. Fuente: Wikipedia

¿Así o mas claro?

Ya que la mayoría de mis lectores son tyros (novatos), me veo en la alegre necesidad de explicarlo de otra manera. SQL Injection es una técnica ingeniosa de ejecutar instrucciones SQL en la base de datos. Estas instrucciones son enviadas desde la aplicación, por ejemplo: escribiendolas en uno de los campos de texto de una pantalla de captura.

Imagina que tienes una pantalla de inicio de sesión como esta:


Es de esperarse que el usuario escriba un nombre de usuario y una contraseña. Sin embargo, sin la debida protección, esta pantalla puede dejar de ser tu primera barrera de protección para convertirse en una puerta abierta, y sin restricciones, a tu base de datos.

Como hacer SQL Injection


Antes de continuar con esta publicación, debo hacer la advertencia de que de ninguna manera quiero promover malas prácticas entre mis lectores. Mi intención principal es enseñar como evitar ser víctima de SQL Injection, pero para eso, antes debo mostrar como se hace.

SQL Injection es muy fácil de hacer si el programador del sistema no ha tomado las debidas precauciones. Para efectos de este tutorial, voy a hacerlo todo en mi PC local, con PHP y MySQL, mas adelante haré una actualización para ASP.NET y SQL Server.

Lo que necesitas saber

Antes de lanzar tu ingenioso ataque necesitas saber varias cosas, entre mas sepas, mayores probabilidades de éxito tendrás. Aquí te dejo una idea básica:

  • Tipo de base de datos, por ejemplo, MS Access, MySQL, Oracle, SQL Server, etc. ¡Todas las bases de datos son vulnerables! No por si mismas, sinó, por la incapacidad del programador.
  • Estructura de la base de datos. Oro solido, si conoces la estructura, ya solo necesitas conocer las instrucicones que deseas ejecutar.
  • Conocimientos suficientes del lenguaje SQL. Dependiendo del daño que trates de hacer. Quizá solo desees alterar los datos, crearte tu propio usuario, pero que tal si... ¡Deseas dañar la estructura de la base de datos!

Para efectos de facilitar la comprensión de este tutorial, voy a mostrarles una estructura de base de datos, además de crear una aplicación totalmente vulnerable a SQL Injection.

Esta es mi estructura de la tabla "Usuarios" en mi base de datos:


Además, éste es el contenido de mi tabla:



Este es el código PHP que vamos a utilizar para la prueba:


function Login($userLogin, $userPassword) {
    $mysqli = new mysqli("127.0.0.1", "root", "admin", "dbo");
    $retorno = false;
    /* verificar la conexión */
    if (mysqli_connect_errno()) {
        printf("Conexión fallida: %s\n", mysqli_connect_error());
        exit();
    }
    $sql = "SELECT Usuario from Usuarios where Usuario = '$userLogin' and Password = '$userPassword' and Activo =1";
    //echo $sql;
    if ($result = $mysqli->query($sql)) {
        /* determinar el número de filas del resultado */
        $row_cnt = $result->num_rows;
        if ($row_cnt != 0)
            $retorno = true;
        /* cerrar el resultset */
        $result->close();
    }

    /* cerrar la conexión */
    $mysqli->close();
    return $retorno;
}


Entonces, si quiero ingresar al sistema, solo debo escribir el nombre de usuario: "admin" y la contraseña: "admin" (sin las comillas). Si instroduzco cualquier otro usuario, mi sistema debe bloquearme el acceso, veamos una prueba:



En el ejemplo de la imagen anterior, introduje intencionalmente un nombre de usuario y contraseña incorectos. ¿Pero que tal si quisiera tratar con el nombre de usuario y contraseña que sea?, ¿Que tal usuario: tyro, Contraseña: jaja? Según el código PHP que tenemos arriba es muy fácil lograrlo, solo tenemos que inyectar código adicional, lo cual es demasiado fácil.


Haríamos lo siguiente:



De esta manera, la consulta original PHP quedaría así:

SELECT Usuario from Usuarios where Usuario = 'admin' and Password = 'jaja' or 1=1; ##' and Activo =1

Toda la magia la hace el caracter ' junto con #. Basta analizar la consulta resultante para comprender el truco.

Y de esa manera lograríamos ingresar al sistema sin ningún problema:


Este es un ejemplo muy básico, pero que nos permite comprender lo que es SQL Injection. Dependiendo de la vulnerabilidad es el nivel del daño que se puede conseguir. Es posible, modificar la instruccion SQL original, alterar registros, insertar registros, borrar tablas, encriptar datos, etc. Las posibildades siempre van de acuerdo entre las capacidades del atacante y las incapacidades del programador.

¿Cómo evitar SQL Injection?


Mientras escribía este dicumento, se acercó uno de mis compañeros del trabajo. Curioso de lo que estaba haciendo, me hizo varias preguntas. Cuando le mostré lo facil que es inyectar SQL se quedó helado. Y no es que fuera un tema raro para él, lo que le sorprendió fué lo facil que es y lo desprotegidos que podemos llegar a estar.
Sería muy fácil entrar al sistema de la universidad y cambiar nuestras calificaciones, o modificar los resultados de una elección, etc. Es por eso que es muy importante protegernos, no solamente de virus, también de ataques SQL Injection.
Para evitar que nuestro código PHP permita la inyección de SQL, comenzaremos por modificarlo para que acepte parametros, como se muestra a contrinuación:

function Login($userLogin, $userPassword) {
    $mysqli = new mysqli("127.0.0.1", "root", "admin", "dbo");
    $retorno = false;
    /* verificar la conexión */
    if (mysqli_connect_errno()) {
        printf("Conexión fallida: %s\n", mysqli_connect_error());
        exit();
    }
    $query = $mysqli->prepare("SELECT Usuario from Usuarios where Usuario = ? and Password = ? and Activo =1");
    $query->bind_param("ss", $userLogin, $userPassword);
    $query->execute();
    $Usuario = null;
    $query->bind_result($Usuario);
    if ($query->fetch()) {
            if (is_null($Usuario)) {
                $retorno = false;
            } else {
                $retorno = true;
            }
        }
    /* cerrar la conexión */
    $mysqli->close();
    return $retorno;
}

En este enlace puedes consultar ma sinformación acerca de la utilización de parámetros en PHP.

También es posible agregar medidas de seguridad, como la purificación de Strings, sin embargo, podemos comenzar con la utilización de parámetros.

Conclusión


SQL Injection es fácil de hacer y fácil de evitar. Todo depende de las capacidades entre el atacante y el programador del sistema. El daño puede ser grande si no se toman las debidas precauciones. Por mas habilidoso que sea un programador, nadie es perfecto. El error y el descuido están escondidos entre el orgullo y la arrogancia de quienes se dicen infalibles.
El exceso de detalles al escribir nuestras lineas, o la pereza por no investigar la mejor manera de hacer las cosas pueden ser grandes debilidades a vencer.

Espero que este tutorial sea de ayuda, al menos para tener una idea de SQL Injection, como hacerlo y como evitarlo.

Gracias
tyrodeveloepr

No hay comentarios:

Publicar un comentario