Tiempo de lectura aprox: 7 minutos, 49 segundos
Cómo funciona un Ataque de Inyección SQL.
La inyección SQL es uno de los métodos más utilizados por los «Hackers», «Crackers» y similares.
Y antes de que saltes, hay que hacer la aclaración: existen «Hackers» de «sombrero blanco», «sombrero gris» y «sombrero negro» y estos últimos, son considerados como «Crackers».
La diferencia estriba en que un «Hackers de sombrero blanco» es un personaje cuya intención es aprender o incluso enseñar, pero carece de motivaciones u objetivos maliciosos.
De todos los ataques que se pueden organizar contra sitios web, la inyección SQL se encuentra entre los tipos más peligrosos y generalizados, y se ha utilizado para causar daños reales a empresas y organizaciones durante varios años.
En pocas palabras, la inyección SQL también conocida como SQLi, utiliza vulnerabilidades en los canales de entrada de un sitio web para apuntar a la base de datos que se encuentra en el servidor de la aplicación web, donde se almacena la información más sensible y valiosa.
Los atacantes pueden utilizar este esquema para robar o manipular datos, obstaculizar la funcionalidad de la aplicación y, en el peor de los casos, obtener acceso como administrador al servidor de la base de datos.
Cómo funciona un Ataque de Inyección SQL
Los ataques de inyección SQL se realizan enviando comandos SQL maliciosos a los servidores de bases de datos a través de solicitudes web.
Se puede usar cualquier canal de entrada para enviar comandos maliciosos, incluidos elementos <input>, cadenas de consulta, cookies y archivos.
Aunque en este artículo hable en general, esto también se aplica a WordPress, ya que también hace uso de una base de datos SQL.
Para escenificar lo que estoy diciendo, usaré como ejemplo la máscara de acceso, en donde se solicita un usuario y una contraseña.
Cuando los usuarios ingresan sus credenciales y presionan el botón «Acceder», la información se publica de nuevo en tu servidor web, donde se combina con un comando SQL. Por ejemplo, en PHP, el código se vería así:
SELECT * FROM users WHERE username='juanito' AND password='123456';
Pero ¿que pasa si el usuario decide poner un nombre como juanito’ or 1=1 —
la aplicación ejecutará el comando:
SELECT * FROM users WHERE username='juanito' or 1=1 -- AND password='123456';
Esto que parece una trivialidad, podría causar que el usuario consiga acceso sea cual sea la contraseña introducida.
Esta es una de las formas más simples de inyección SQL; Con un poco más de esfuerzo, el mismo usuario puede insertar nuevas cuentas de usuario y eliminar o modificar cuentas de usuario existentes.
En las páginas que muestran resultados (como las de los buscadores), se puede usar el mismo esquema para mostrar registros e información que de otro modo se restringirían a los visitantes normales, o para cambiar el contenido de los registros.
En casos más severos, donde la conexión al servidor de la base de datos se realiza a través de una cuenta administrativa (como «root» en MySQL o «sa» en MS SQL Server), el atacante puede llegar a comprometer completamente el sistema operativo del servidor.
En los servidores de Windows, esto puede manifestarse en el atacante que ejecuta procedimientos almacenados extendidos como xp_cmdshell.
En un caso, los atacantes utilizaron una vulnerabilidad de inyección SQL para crear cuentas de usuario en el servidor comprometido, habilitar la función de «Escritorio remoto», configurar carpetas compartidas SMB y cargar malware, además de prácticamente desordenar todo lo que estaba almacenado en la base de datos.
Cómo protegerte de los ataques de inyección SQL
Dado que los canales de entrada del usuario son el vector principal para los ataques de inyección SQL, la mayoría de los métodos defensivos implican controlar y examinar la entrada del usuario para los patrones de ataque.
Aquí hay varias medidas que pueden garantizar la seguridad de entrada del usuario.
Nunca confíes en las entradas de un usuario
La primera regla general sobre la entrada del usuario es «no confíes y verifica», lo que significa que todas las formas de entrada del usuario deben considerarse maliciosas a menos que se demuestre lo contrario.
Esto se aplica no solo a los cuadros de entrada simples, como las áreas de texto y las cajas de texto, sino también todo lo demás, como entradas ocultas, parámetros de cadena de consulta, cookies y cargas de archivos.
El hecho de que la interfaz de usuario del navegador no permita al usuario manipular una entrada, no significa que no pueda ser manipulada.
Existen herramientas simples como «Burp Suite» que permiten a los usuarios capturar solicitudes HTTP y modificar cualquier cosa, incluidos los valores de formulario ocultos, antes de enviarlos al servidor.
Y si crees que eres inteligente al codificar tus datos en Base64, los usuarios malintencionados pueden decodificarlos, modificarlos y volver a codificarlos fácilmente.
Valída las entradas en el servidor
La validación es el proceso de asegurarse de que los usuarios proporcionen el tipo correcto de entrada y de neutralizar cualquier posible comando malicioso que pueda estar incorporado en la cadena de entrada.
Por ejemplo, en PHP, puedes usar mysql \ _real \ _escape \ _string () para escapar los caracteres que pueden cambiar la naturaleza del comando SQL.
Una versión alterada del código de inicio de sesión mencionado anteriormente sería la siguiente:
$con=mysqli_connect("localhost","user","password","db"); $username = mysqli_real_escape_string($con, $_POST['username']); $password = mysqli_real_escape_string($con, $_POST['password']); $sql_command = "select * from users where username = '" . $username; $sql_command .= "' AND password = '" . $password . "'";
Esta simple modificación protegería tu código contra el ataque que se presentó al agregar un carácter de escape (\) delante de las comillas simples que el usuario malicioso agregó intencionalmente.
Una nota sobre la validación: si has añadido funciones de validación del lado del cliente, bien hecho. Pero no confíes en ello como una medida defensiva contra los ataques de inyección SQL.
Si bien las funciones del lado del cliente pueden dificultar aún más el envío de entradas maliciosas a tu servidor, estas funciones también pueden evitarse fácilmente con algunos ajustes y herramientas del navegador. Por lo tanto, debes complementarlo con la validación del lado del servidor.
Pero los piratas informáticos pueden burlarlos con un poco de paciencia y sutilezas. Recuerda: Nunca puedes ser demasiado cauteloso.
Usa parámetros de comando
Los parámetros del comando constituyen una mejor alternativa para escapar, se definen agregando nombres de marcador de posición en los comandos SQL, que luego serán reemplazados por la entrada del usuario.
Este es un ejemplo escrito en C#, de cómo hacer la validación con parámetros de comando para protegerte de la inyección SQL:
SqlCommand cmd = new SqlCommand ("SELECT * FROM users WHERE username=@username AND password=@password",con); SqlParameter username = new SqlParameter(); username.ParameterName = "@username"; username.value = txtUsername.Text; cmd.Parameters.Add(username); SqlParameter password = new SqlParameter(); password.ParameterName = "@password"; password.value = txtPassword.Text; cmd.Parameters.Add(password);
Empieza creando un objeto SqlCommand y usando el paradigma @parameter_name en la cadena de comando donde se debe insertar la entrada del usuario.
Luego crea instancias de objetos SqlParameter, en los que insertas la entrada del usuario, en lugar de concatenarla directamente con la cadena de comando.
Finalmente, agrega el objeto SqlParameter a la colección Parámetros del objeto SqlCommand, que reemplazará los parámetros con la entrada proporcionada.
Especifica explícitamente tu entrada
El lenguaje PHP es uno de los lenguajes débilmente tipados, lo que significa que generalmente no define tipos de datos para variables, y el lenguaje se encarga automáticamente de convertir diferentes tipos de datos entre sí.
Las conversiones explícitas pueden actuar como un acceso directo a la entrada de escape donde intervienen tipos que no son cadenas.
Por tanto, si esperas que el usuario ingrese un int para el parámetro age, puedes garantizar la seguridad de la entrada con el siguiente código en PHP:
$age = (int)$_POST['age'];
Ten en cuenta que este fragmento sólo valida el tipo de entrada, no su rango. Por lo tanto, tendrás que ejecutar otro código adicional para asegurarte de que el usuario no ingrese una edad negativa, o no realista, como 1300.
Además, otra práctica recomendada es evitar el uso de comillas simples en los comandos SQL en los que está involucrada la entrada sin cadenas.
Por tanto, en lugar de usar el siguiente código …
$sql_command = "select * from users where age = " . $age;
es mucho más seguro usar:
$sql_command = "select * from users where age = '" . $age . "'";
Cómo eliminar las vulnerabilidades de inyección SQL
Como práctica general, debes comprobar el código de cada página en busca de los lugares donde combinas los contenidos, comandos, cadenas, etc. de la página con fuentes que pueden provenir de los usuarios.
Examinar tu código fuente en busca de vulnerabilidades y agujeros de seguridad debería ser una parte inherente de tu proceso de desarrollo de software.
También puedes usar herramientas de escaneo como sqlmap para rastrear las páginas de tu sitio en busca de posibles vulnerabilidades de inyección SQL.
De hecho, los piratas informáticos utilizan con frecuencia esta herramienta para encontrar y explotar vectores de ataque de inyección SQL en sitios web específicos, entonces, ¿por qué no usarla para hacerlos más seguros?
La última línea de defensa
No importa cuánto fortifiques la seguridad de tu sitio web, debes prepararse para el día en que se realice una inyección SQL.
Después de todo, como es ampliamente conocido en la industria de la ciberseguridad, que los defensores tienen que ganar cada pelea, pero los hackers solo tienen que ganar una vez.
Te presento algunos consejos que te ayudarán a minimizar el daño cuando te conviertas en una víctima de inyección SQL.
Limita los privilegios de administración
Usar las cuentas «root» o «sa» para conectar tu aplicación web a tu servidor de base de datos es uno de los peores errores que puedes cometer.
Como ya he mencionado, una cuenta administrativa comprometida puede potencialmente dar acceso a los piratas informáticos a todo el sistema.
Incluso las cuentas no administrativas que tienen acceso a todas las bases de datos dentro de un servidor pueden ser perjudiciales, especialmente si el servidor de la base de datos se comparte entre diferentes aplicaciones y bases de datos.
Por lo tanto, es mejor usar una cuenta que solo tenga permisos simples de lectura y escritura para la base de datos específica que se encuentra detrás de tu sitio web, por lo que en caso de que tu sitio sea pirateado mediante inyección SQL, el alcance del daño permanece dentro de los límites de esa base de datos única.
Un enfoque más avanzado sería utilizar conexiones separadas para segmentos de código que leen o escriben en tu base de datos, y reducir aún más los permisos y roles para cada segmento.
Por ejemplo, las páginas de la lista, que no realizan modificaciones en la base de datos, pero utilizan ampliamente los parámetros de búsqueda, pueden codificarse para usar una conexión de solo lectura a la base de datos con el fin de fortalecer aún más su código contra accidentes.
En MySQL, mejorarás la seguridad limitando el acceso a la cuenta de usuario a rangos específicos de direcciones IP en lugar del modelo «%», para evitar el acceso a cuentas comprometidas desde ubicaciones remotas.
Cifrar datos confidenciales
Cifra los datos confidenciales en tu base de datos. Esto incluye contraseñas, preguntas y respuestas de seguridad, datos financieros, información de salud y otra información que podría ser útil para actores maliciosos.
Esto asegurará que incluso si los piratas informáticos ponen sus manos en tus datos, no podrán explotarlos de inmediato, lo que te dará tiempo para descubrir la violación, tapar el agujero y tomar otras medidas reactivas, como forzar el restablecimiento de contraseñas, lo que que asegurará que los datos robados pierdan su valor antes de que el atacante los descifre.
Si estás modificando tus contraseñas, usa algoritmos fuertes como SHA-2 para la protección de contraseñas.
MD5 y SHA-1 están obsoletos y se pueden revertir.
Para otras formas de encriptación, ten cuidado dónde guardas las llaves y nunca pongas todos tus huevos en una misma cesta.
No tendría sentido utilizar el cifrado si las claves están justo al lado de los datos cifrados y los piratas informáticos accederán fácilmente a ellos tan pronto como comprometan el servidor.
No almacenes datos confidenciales si no los necesitas
Siempre que almacenes información en tu base de datos, considera cuán dañino puede llegar a ser si cae en las manos equivocadas, y decide si realmente necesitas almacenarla o no.
El truco de «Ashley Madison», que reveló los secretos oscuros y la información más íntima de unos 37 millones de personas en Internet y causó daños graves, en parte debió su éxito al hecho de que el proveedor se había abstenido de borrar información confidencial de sus bases de datos.
En resumen, no almacenes información confidencial en tu base de datos a menos que realmente necesites hacerlo. E incluso entonces, elimina la información cuando ya no esté en uso.
Conclusión
La inyección SQL ha existido durante décadas y probablemente continuará encabezando las listas de vulnerabilidad en los próximos años.
Se necesitan algunos pasos fáciles, pero bien calculados, para protegerse y proteger a tus usuarios contra esta vulnerabilidad y, debes estar entre tus principales prioridades al auditar tu código fuente para detectar agujeros de seguridad.
La clave para evitar ser víctima de la próxima gran violación de datos de inyección SQL es primero, controlar y validar la entrada del usuario, y segundo, prepararse para el «cuándo», en lugar de el «si».
Si te interesa el tema y quieres ver cómo ataja el problema la gente de WordPress.org, tienes un artículo interesante en: Limpiar un WordPress infectado.
También puedes instalar, para tu mayor seguridad, un plugin como Block Bad Queries.
Estoy preparando una entrada con una mayor descripción de este ataque informático y su funcionamiento.
Mientras tanto, #QuédateEnCasa, juega, experimenta y, sobre todo, ¡divertirte!
¡Gracias por leernos!
¡Tus comentarios y preguntas nos ayudan a mejorar, por favor comenta!