Detengamos los SQL Injection. Por favor!

Si eres programador y no estas seguro si tu codigo es vulnerable a SQL Injection este post es para ti

Publicado por AlbertoBSD el 2019-12-30 17:42:03

Y fue así como me hackearon la base de datos!

Un poco de contexto para empezar y no me han hackeado la base de datos por cierto.

OWASP: (Open Web Application Security Project) por sus siglas en inglés es una comunidad Online que produce artículos, metodologías, documentación, herramientas y tecnologías en el campo de seguridad para aplicaciones web, de forma gratuita y siempre disponible.

OWASP a lo largo de la pasada década a sacado algunos TOPs de vulnerabilidades críticas, por su alcance he impacto en la seguridad y en todas ellas a existido el primer puesto las inyecciones SQL

Y si hoy finales de 2019 inicios del 2020 sacaran el TOP de nuevo me la juego a que nuevamente los SQL Injection estarían en primer lugar, no es por nada pero cada que entro a la comunidad de elhacker.net siempre veo alguien preguntando algo sobre X cosa y en el código que ponen de ejemplo viene siempre una Consulta tipo SQL vulnerable

Ejemplo: Problema con clonar input y traer datos. Preguntan algo sobre Javascript (Bastante feo el codigo) pero pone una consulta SQL Vulnerable WTF!!!

Aviso la siguiente linea de Codigo es VULNERABLE, si la utilizan o si programan de manera similar les van a Hackear la pagina, la base datos.

$sql = "SELECT * FROM Productos WHERE Codigo = '$cod'";

El problema persiste, por que es cierto que cuando estas aprendiendo a programar la seguridad es en lo último que te fijas. Sin embargo terminas de aprender y sales directo al mercado laboral y comienzas a plantar donde sea que llegues código BASURA como la linea anteriormente mencionada. Ojo y no me malinterpreten, puede que escriban las mejores estructuras de datos, las mejores abstracciones de clases, que optimicen el código y lo hagan 200 veces más rápido que antes, pero si escriben UNA SOLA linea VULNERABLE de código, los van a hackear 200 veces más rápido.

¿Cómo solucionamos los SQL Injection?

La primera medida es aprender a realizar un SQL Injection sobre un código vulnerable y una vez que conozcamos el riesgo y alcance que esta vulnerabilidad tiene. Solo hasta entonces podremos ver la necesidad de solucionar este problema y programar mejor para mitigar este tipo de ataques

Pensemos en el caso más común de un login en PHP que aparte de ser vulnerable a SQL Injection, también tiene la vulnerabilidad de Enviarlos lo datos vía GET y guardar los password en texto plano en la base de datos pero eso mis lectore es material de otro post

La siguiente linea de codigo es Vulnerable favor de no utilizar es para el ejemplo

$query = "select user, password from users where user = '".$_GET["usuario"]."' and password = '".$_GET["password"]."'";

Para el ejemplo anterior vamos a ver cómo es posible:

  • Ingresar al sistema como cualquier usuario
  • Extraer todos los passwords
  • Y si el sistema es vulnerable a XSS, ejecutar un XSS

Para ejemplificar el problema anterior pueden practicar en una sección h4x0r que he habilitado en mi pagina /-/7/ pero antes de ir allá, favor de terminar de leer este post primero.

Ingresar al sistema como cualquier usuario para realizar esta acción podemos utilizar cualquier de las siguientes lineas como parámetro de usuario:

' or id=1 --
' or id=2 --
' or id=3 --
...

Extraer todos los passwords estos solo es posible si la pagina te muestra el nombre del usuario que acaba de ingresar (Con los datos directamente tomados de la consulta vulnerable) para realizar esta acción nos ayudaremos del operador unión que esta casi presente en todos lenguajes SQL

' union select password as user,user as password from users where id = 1 --

El código anterior podría ser igual de valido para cualquier usuario, también requiere un poco de conocimiento de los campos de la base de datos, sin embargo estos los podemos sacar con los mensaje de error de la misma base de datos y/o con algo de sentido común

Y si el sistema es vulnerable a XSS, ejecutar un XSS eso serial posible nuevamente al operador union con el siguiente codigo

' union select "<script>alert('XSS');</script>","dummy" --

Entonces ¿Como solucionamos los SQL Injection?

Para empezar dejemos de contruir las consultas SQL manualmente como lo hemos estado haciendo

Lo mejor que podemos realizar es teneer funciones que validen el tipo de dato que estamos insertanto y lo sanitizen deacuerdo al charset que el servidor espera recibir

Si estan utilizando PHP es mejor dejar esto en manos de PDO (PHP Data Objects) y dejar que las consultas se ejecuten mediante Statements correctamente contruidos, aun asi el PDO tiene que estar correctamente configurado, actualizado y en peor de los casos realizar pruebas manualmente

Para el ejemplo mencionado esto se corrige mediante PDO con el siguiente código:

	$query = "select user, password from users where user = :user and password = :password";
	$stmt = $pdo->prepare($query);
	$stmt->bindParam(':user', $_GET["user"]);
	$stmt->bindParam(':password', $_GET["password"]);
	$stmt->execute();

El código anterior también tiene un problema de seguridad lógico y es que NO DEBEMOS DE GUARDAR PASSWORDs EN TEXTO PLANO

Existen varios casos donde incluso con PDO y las consultas mediante statements tambien pueden ser vulneradas, para estos casos hago referencia a Are PDO prepared statements sufficient to prevent SQL injection? y a SQL injection that gets around mysql_real_escape_string() Todo esto depende de nuestra configuracion de la base de datos y la configuracion de la conexion PDO

Otro tema importante es el charset de la base de datos, pero eso ya es otro tema

Saludos!


Una entrega nueva cada Lunes

please login
Login to comment
Loging with github