En primer lugar, debemos revisar la parte del servidor web. Las vulnerabilidades que nos podemos encontrar serán:
- Comunicación insegura entre cliente y servidor. Es muy importante que la comunicación entre cliente y servidor esté cifrada, sobre todo cuando se trata de envíos de formularios, por ejemplo, para autentificarse en sitio web. En muchas ocasiones se configura el sitio web para usar cifrado con una configuración débil, permitiendo protocolos inseguros, como SSLv2 y SSLv3, o suites de cifrado vulnerables, como MD5. Esto dará una falsa sensación de seguridad, el cliente verá que hay un certificado, que el sitio web aparentemente está cifrado, y, sin embargo, por culpa de los protocolos permitidos podría ser relativamente fácil descifrar esta comunicación. Es por ello que es necesario revisar el estado de la calidad en la configuración de nuestros certificados.
- Software desactualizado. Una vez desplegado el sistema, independientemente de que se hiciese el trabajo de forma correcta, pasado el tiempo el software se desactualiza. Se localizan vulnerabilidades, se corrigen en versiones posteriores, etc. Es necesario llevar un control de las versiones utilizadas, así como mantener el software actualizado, en el menor tiempo posible desde que se libera una nueva versión. En caso contrario, al cabo de un tiempo nuestro sistema será vulnerable y existirán exploits públicos que permitirán atacarlo.
- Configuración débil, por defecto o mal configurado. Esto suele producirse por intentar desplegar el servicio lo más rápido posible o por una confianza excesiva en el software utilizado, incluso por desconocimiento. Cuando se expone a Internet un sistema con su configuración por defecto, si se encuentra una vulnerabilidad en el mismo, el exploit por defecto funcionará. Es necesario revisar el servicio a desplegar y buscar una configuración suficientemente fuerte.
En segundo lugar, aunque la aplicación esté desplegada sobre una plataforma correctamente fortificada, la aplicación puede tener vulnerabilidades por una mala codificación.
Las vulnerabilidades más comunes en una aplicación web son:
1. Inyección de comandos
El propósito del ataque de inyección de comandos es inyectar y ejecutar comandos especificados por el atacante en una aplicación vulnerable. En situaciones como esta, la solicitud que ejecuta los comandos no deseados del sistema es como un shell del sistema, y el atacante puede hacerse pasar por cualquier usuario del sistema autorizado. Sin embargo, los comandos se ejecutan con los mismos privilegios y en el mismo entorno de la aplicación. Los ataques de inyección de comandos son posibles en la mayoría de los casos debido a la no validación correcta de los datos de entrada, que pueden ser manipulados por el atacante (formularios, cookies, encabezados HTTP, etc.)
Existe una variante del ataque basada en la inyección de código. Las diferencias con la inyección de comandos es que el atacante añade su código al código existente. De esta manera, el atacante extiende la funcionalidad por defecto de la aplicación sin la necesidad de ejecutar comandos del sistema. El código inyectado se ejecuta con los mismos privilegios y en el mismo entorno de la aplicación.
Un ataque de inyección de comando del sistema operativo se produce cuando un atacante intenta ejecutar comandos del sistema a través de un nivel de aplicación vulnerable. Las solicitudes se consideran vulnerables a los ataques de inyección de comandos OS si utilizan la entrada del usuario en un nivel del sistema de comandos.
Las vulnerabilidades por inyección de comandos normalmente se producen cuando:
- Los datos introducidos en una aplicación proceden de una fuente no confiable.
- Los datos son parte de una cadena que se ejecuta como un comando por la aplicación.
- Al ejecutar el comando, la solicitud ofrece a un usuario malintencionado un privilegio o capacidad que el atacante de otro modo no obtendría.
Ya se ha comentado que uno de los mayores problemas que provoca esta vulnerabilidad es la falta de filtrado de las entradas de los usuarios. Es recomendable filtrar las mismas para asegurar que no se introduce código malicioso. Utilizad las funciones:
- escapeshellarg() que filtra los argumentos
- escapeshellcmd() que filtra los comandos no estáticos
2. Cross-Site Scripting (XSS)
Esta es una vulnerabilidad o, mejor dicho, un conjunto de vulnerabilidades, que permiten, utilizando los parámetros de entrada de la aplicación, modificar y añadir código a la misma.
Son vulnerabilidades que se encuentran en el servidor, pero que están destinadas a atacar al cliente.
Generalmente, se necesita que el cliente siga un enlace de la aplicación, en el que se ha modificado algún parámetro, para permitir añadir código que se ejecutará en el navegador del cliente.
Normalmente, el código inyectado será html o JavaScript y la intención será un robo de cookies del cliente, predicción del id de sesión, etc.
Esta vulnerabilidad se aprovecha de la confianza del cliente en el sitio web: verá que es el dominio de la aplicación y que, al seguir el enlace, llega realmente al sitio web que quería, y pensará que no hay suplantación del mismo.
Básicamente, podemos agrupar los XSS en dos grupos:
– XSS reflejados: el código modificado se elimina al cargar la página de nuevo. Está basado en la URL y, por tanto, al recargar la página se elimina el mismo.
– XSS persistentes: el código modificado queda almacenado en la web.
La forma de corregir esta vulnerabilidad es filtrar y validar todas las entradas de la aplicación. No se debe utilizar nunca una variable que se recibe desde el cliente confiando en que esta tendrá un valor correcto. Los lenguajes de programación incluyen diferentes funciones que permiten filtrar el contenido de las variables, dependiendo de dónde las vayamos a utilizar.
3. Cross Site Request/Reference Forgery (CSRF)
Esta vulnerabilidad es una evolución de los XSS. En este caso, se va a explotar la confianza en el servidor sobre el cliente. Es decir, nos haremos pasar por un cliente legítimo, utilizando datos parciales del mismo.
Esta vulnerabilidad está presente en formularios. Cuando estos se envían al servidor, es necesario asegurarse de que la petición es legítima y debemos asegurarnos de que el cliente ha realizado la petición, realizando los pasos previos necesarios.
La forma más común para eliminar esta vulnerabilidad o, al menos, mitigarla, es la inclusión de tockens dinámicos. En los actuales FrameWorks, suelen incluirse mecanismos para añadir esta protección a los formularios, de una forma muy sencilla. En algunos, por ejemplo, Laravel (utilizado para desarrollo de aplicaciones en PHP), basta añadir una etiqueta a la plantilla del formulario para que se añada al mismo el tocken anticsrf.
A continuación, os muestro los nombres de los diferentes XSS más comunes, que dependen del lugar donde se consiga inyectar el código deseado.
- DOM Cross Site Scripting (DOM XSS)
- Cross Site Flashing (XSF)
- Cross Frame Scripting (XFS)
- Cross Zone Scripting (XZS)
- Cross Agent Scripting (XAS)
- Cross Referer Scripting (XRS)
4. SQL INJECTION
Si los ataques XSS son peligrosos, ya que pueden provocar un robo de sesión, los SQLi lo son aún más porque permiten acceder y manipular la BBDD. La idea es modificar las consultas que hace la aplicación a la base de datos, aprovechando las entradas de usuario a la aplicación.
Existen diferentes ataques de SQL injection, dependiendo de cómo se consiga inyectar y modificar la consulta para obtener los datos que se desean.
- Bypass de un login mediante SQL Injection
- SQL Injection (mediante UNION)
- Serialized SQL Injection
- Boolean-Base SQL Injection
- Time-Base SQL Injection
- Heavy-Queries SQL Injection
- Stack-Queries
Para prevenir los SQLi, se deben parametrizar las consultas y es necesario filtrar y comprobar el valor de las entradas. También es muy importante restringir al máximo los permisos del usuario con el que la aplicación se conecta a la BBDD y, por supuesto, para cada BBDD utilizar un usuario diferente. Esto es muy importante, y aunque es una mala práctica usar una misma instancia del motor de BBDD para diferentes aplicaciones, es un escenario muy común. Por este motivo, si un usuario de la BBDD tiene permisos sobre varias BBDD de diferentes aplicaciones y una de estas presenta esta vulnerabilidad, el atacante podría obtener los datos del resto de aplicaciones.
Además de esto, es muy importante ocultar los errores provocados por consultas en BBDD. Esto es porque la forma de detectar un SQLi es intentar forzar un error (la típica ‘) y, una vez se comprueba que existe, si se muestra al usuario, este puede extraer información, como el motor de BBDD usado, etc., con lo que se le facilitará la realización del ataque.
5. INSECURE DESERIALIZATION
Es una vulnerabilidad que se produce cuando se usan datos no confiables para abusar de la lógica de una aplicación, infligir un ataque de denegación de servicio (DoS) o incluso ejecutar código arbitrario cuando se deserializa.
Para entender esta vulnerabilidad tenemos que tener dos conceptos muy claros:
- Serialización. Se refiere a un proceso de conversión de un objeto a un formato que puede persistir en el disco enviado a través de secuencias o enviado a través de una red. El formato en el que se serializa un objeto puede ser binario o texto estructurado (por ejemplo, XML, JSON YAML …). JSON y XML son dos de los formatos de serialización más utilizados en las aplicaciones web.
- Deserialización. Se refiere a transformar los datos serializados provenientes de un archivo, flujo o socket de red en un objeto.
En las aplicaciones web es normal utilizar la serialización y deserialización de forma regular y la mayoría de los lenguajes de programación incluso ofrecen funciones nativas para serializar datos (especialmente en formatos comunes como JSON y XML). Es importante comprender que la deserialización segura de objetos es una práctica normal en el desarrollo de software. Sin embargo, el problema comienza cuando se deserializa la entrada del usuario que no es de confianza.
La mayoría de los lenguajes de programación ofrecen la posibilidad de personalizar los procesos de deserialización. Desafortunadamente, con frecuencia es posible que un atacante abuse de estas funciones de deserialización cuando la aplicación está deserializando datos no confiables que controla el atacante. Los exitosos ataques de deserialización inseguros podrían permitir a un atacante realizar ataques de denegación de servicio (DoS), desvíos de autenticación y ataques de ejecución remota de código.
Con el fin de reducir significativamente la posibilidad de introducir vulnerabilidades de deserialización inseguras, se deben utilizar métodos no lingüísticos para la deserialización, como JSON, XML o YAML.
Sin embargo, tened en cuenta que todavía puede haber casos en los que sea posible introducir vulnerabilidades incluso cuando se utilizan dichos formatos de serialización. La principal es la entidad externa XML (XXE), que es endémica de una variedad de analizadores XML en una variedad de lenguajes de programación y bibliotecas de terceros.
En Python se usa PyYaML, una de las bibliotecas de análisis de YAML más populares para Python.
La forma más sencilla de cargar un archivo YAML utilizando la biblioteca PyYAML en Python es llamar a yaml.load (). En este caso debemos utilizar el método yaml.safe_load() que es más seguro. Es importante tener en cuenta que todas las aplicaciones escritas en Python, Java, ASP.Net y otros lenguajes son susceptibles a vulnerabilidades de deserialización inseguras. Este tipo de ataques son difíciles de realizar, pero no por eso resultan menos peligrosos.
6. XXE (XML EXTERNAL ENTITY)
Consiste en la falsificación de solicitud de servidor (SSRF), mediante el cual un atacante es capaz de causar divulgación de datos confidenciales, denegación de servicio, falsificación de solicitudes del lado del servidor, escaneo de puertos desde la perspectiva de la máquina donde se encuentra el analizador y otros impactos del sistema.
Es decir, es una inyección que aprovecha una mala configuración del intérprete XML permitiendo incluir entidades externas, el ataque se realiza contra la aplicación que interpreta lenguaje XML en sus parámetros.
Para poder controlar este tipo de vulnerabilidad, ya que todo documento XML se comunica desde un cliente que no es de confianza, no es posible validar selectivamente o escapar de datos contaminados dentro del identificador del sistema en la DTD. Es aconsejable configurar el procesador XML de la siguiente forma: utilizar una DTD estática local y no permitir ninguna DTD declarada incluida en el documento XML.
Podéis encontrar más información sobre cómo defenderse de los ataques XXE aquí.
He intentado explicar de una forma sencilla las principales vulnerabilidades. ¡Espero que os haya gustado!
Más información: