Ataque y Defensa en Entorno de Pruebas, de Aplicaciones Web

Protocolo HTTP
Una de las partes más importantes de cualquier auditoría de hacking ético es conocer las bases, estructuras y protocolos de las tecnologías que se van a auditar.

De esta manera, es muy importante conocer los protocolos que intervienen en la comunicación entre el navegador del usuario y el servidor y la estructura de un aplicativo web.

Este primer apartado trata de proveer estas nociones básicas al alumno para que más tarde pueda entender de de qué manera surgen algunas de las vulnerabilidades web.

Arquitectura de un aplicativo web
Con el auge de los aplicativos web dinámicos se generó una nueva estructura para poder dividir estos aplicativos en 3 capas bien diferenciadas que en conjunto conforman el aplicativo web, esta estructura se la conoce como Modelo-Vista Controlador (MVC). Cada una de estas capas se encarga de la gestión de una serie de funcionalidades.

La ventaja de este modelo es que en cualquier momento se puede sustituir cualquiera de estas capas por otra capa que asuma las mismas funciones y que aporte más ventajas. Por ejemplo, el uso de una nueva tecnología o lenguaje de programación, sin influir en las otras capas. A continuación se enumeran las distintas capas:

  • Controlador: Es la capa que se encarga de recoger y gestionar los datos de los usuarios para que sean tratados. Sirve de enlace entre las otras dos capas, es decir, con los datos que le indica el usuario (dirección URL y parámetros de entrada) solicita los datos al modelo y se los comunica a la vista.
  • Modelo: Esta capa se encarga de gestionar y mantener los datos de la aplicación, se apoya en la base de datos.
  • Vista: Por su parte la vista se corresponde con la representación visual de los datos, genera el código HTML y JavaScript que se devolverá al usuario para representar los datos obtenidos.

Introducción al protocolo de comunicaciones HTTP
El protocolo HTTP (Protocolo de transferencia de Hipertexto) es el protocolo de comunicación que permite intercambiar información en la “Word Wide Web” (Internet).

Define la sintaxis y la semántica que utilizan los elementos de software de la arquitectura web (clientes, servidores, proxies) para comunicarse.

La comunicación se realiza mediante una arquitectura Petición-Respuesta, los clientes (navegadores web, aplicativo móvil, etc.) envían peticiones HTTP al servidor. El servidor por su parte responde a cada petición con una respuesta HTTP y cierra el canal de conexión. Si el cliente necesita seguir comunicándose necesita volver a establecer una comunicación mediante el envío de una petición.

El protocolo HTTP es un protocolo sin estado. Es decir, no guarda ninguna información sobre conexiones anteriores. Este hecho se produce a que el canal de comunicaciones no permanece abierto, es decir, el cliente envía una petición HTTP y el servidor le devuelve una respuesta HTTP a su petición y se cierra el canal de comunicaciones.

El desarrollo de aplicaciones web necesita frecuentemente mantener estado. Para suplir esta carencia se hace uso del mecanismo de las cookies, que es información que un servidor puede almacenar en el sistema cliente.

Este mecanismo permite a las aplicaciones web entregarle al navegador del cliente un identificador de sesión que identifica al usuario en la aplicación (una vez que el usuario ha realizado una autenticación satisfactoria en el sistema).

En cada intercambio de información, el cliente envía al servidor (en las cabeceras de la petición HTTP) este identificador de sesión almacenado en la cookie. De esta manera, el servidor puede verificar el usuario de la aplicación con el que se está comunicando.


Análisis de la petición HTTP
Tal y como hemos explicado en el apartado anterior, la comunicación en el protocolo HTTP se realiza mediante el envío de peticiones HTTP por parte del cliente y la respuesta HTTP, por parte del servidor para contestar a cada petición enviada por el cliente.

Las peticiones originadas en el cliente tienen una estructura en la que podemos diferenciar los siguientes elementos:

  • Línea de petición: Es la primera línea de la petición, incluye el método HTTP utilizado (GET, POST…), el path de la url a consultar y la versión del protocolo utilizada.
  • Cabeceras de la petición: Contienen todas las cabeceras de la petición HTTP, como puede ser cookies, User-Agent (indica el navegador utilizado por el cliente), Host (indica el servidor remoto), etc.
  • Cuerpo de la petición: Este Apartado puede estar incluido (método POST) o no incluirse (método GET, HEAD, OPTIONS).

En caso de encontrarse presente, contiene los parámetros que se han de enviar al servidor para hacer una consulta. En el siguiente ejemplo se envían 2 parámetros (“bookId” y “author”) el servidor recogerá estos parámetros y, dependiendo de la acción indicada en la URL del path, podrá ejecutar una funcionalidad de búsqueda o incluso una funcionalidad de inserción en la base de datos los valores indicados.


Métodos HTTP

Dentro del protocolo HTTP existen varios métodos que pueden utilizarse en la cabecera de la petición. A continuación se muestra un listado de los mismos y sus características más comunes.
  • GET: Este método no incluye cuerpo de la petición. La información transmitida a través de los parámetros se envía en la propia dirección URL.
  • POST: Este método incluye un cuerpo de la petición. En este cuerpo de la petición HTTP se incluye la información que queremos que procese el servidor. Esta información se puede transmitir en el cuerpo de la petición HTTP de varias maneras como, por ejemplo, mediante el uso de parámetros, datos estructurados en formato JSON o XML o incluso datos binarios como pudiera ser la subida de un fichero o una imagen.
  • HEAD: Realiza una petición HTTP igual que realizaría el método GET pero le indica al servidor que sólo quiere obtener las cabeceras de respuesta.
  • OPTIONS: Solicita al servidor que le indique los métodos HTTP que acepta.
  • PUT: Carga, hace upload de un fichero en el servidor o hace una inserción de información en el servidor.
  • DELETE: Borra el recurso o la información indicada.
  • TRACE: Le indica al servidor que le muestre en la respuesta todos los datos que le envíes en el mensaje de petición. Se utiliza con fines de depuración.

Cabeceras de la petición
Las cabeceras de la petición indican cierta información adicional al servidor que puede utilizar para componer una respuesta adecuada. Se puede consultar un listado bastante completo de cabeceras en la siguiente dirección URL (https://en.wikipedia.org/wiki/List_of_HTTP_header_fields).

A continuación se muestran las cabeceras HTTP más comunes:

  • Accept: Indica los tipos de contenido que acepta que el servidor le incluya en las respuestas (texto, imágenes, información comprimida, XML, JSON, etc.).
  • Accept-Charset: Indica el conjunto de caracteres que se aceptan para que el servidor mande la respuesta con ese conjunto de caracteres establecido (UTF-8).
  • Accept-Encoding: Especifica el listado de codificaciones que se aceptan para que el servidor se ajuste a ellas a la hora de componer su respuesta (gzip, deflate).
  • Accept-Language: Indica el lenguaje que está utilizando el navegador del usuario (en-US).
  • Authorization: Cabecera que puede utilizarse para realizar algún tipo de autenticación (Como la autenticación básica o la autenticación basada en JSON Web Tokens) puede sustituir o complementar a la autenticación vía Identificador de Sesión indicado en una Cookie.
  • Cache-Control: Controla la política de cache y si la respuesta que envíe el servidor ha de almacenarse en la caché del navegador.
  • Cookie: Almacena cierta información enviada por el servidor previamente para que se incluya en cada petición realizada por el cliente. Normalmente es el mecanismo utilizado para otorgar y transmitir identificadores de sesión, aunque se puede almacenar cualquier información que se considere oportuna.
  • Content-Length: El tamaño que ocupa la petición en Bytes.
  • Content-Type: El tipo de contenido de la petición, sólo se utiliza cuando el método es POST o PUT para indicar el tipo de contenido que se incluye en el cuerpo de la petición HTTP (imagen, fichero binario, etc.).
  • Date: Fecha y hora de la petición.
  • Host: Nombre de dominio de host o dirección IP, el uso de esta cabecera es obligatoria a partir de HTTP/1.1(www.example.com).
  • Referer: Indica la dirección URL inmediatamente anterior a la petición actual. Es decir, indica desde que path proviene la petición del usuario.
  • User-Agent: Indica el navegador y sistema operativo utilizado por el cliente que realiza la petición (Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0).

Estructura de la dirección URL
La dirección URL de una petición web presenta una determinada estructura que indica la funcionalidad del aplicativo solicitado en el dominio indicado. Además, puede contener información de los datos de entrada que necesita la funcionalidad para su correcto funcionamiento. La siguiente ilustración muestra la estructura de una dirección URL:

A continuación, se muestra una breve descripción de cada una de las partes involucradas.
  • Protocolo: Es el protocolo de comunicaciones elegido para la transferencia de información entre el navegador del usuario y el servidor. Normalmente HTTP (protocolo sin cifrar) o HTTPS (Protocolo cifrado).
  • Dominio: Representa el dominio al que queremos acceder.
  • Path: Representa la ruta dentro del dominio al que queremos acceder, normalmente se corresponde con una funcionalidad determinada que ofrece el aplicativo.
  • Parámetros: Es el sistema que presenta el protocolo para entregar los datos de entrada a la funcionalidad indicada. Se componen del par nombre/valor dónde se indican el nombre de las distintas variables de entrada al aplicativo y el valor que toman respectivamente.
Análisis de respuesta HTTP
De la misma manera, en la comunicación HTTP el servidor genera una respuesta HTTP que contiene una estructura similar a las peticiones HTTP (Enviadas por el cliente). En estas respuestas HTTP (Enviadas por el servidor) podemos diferenciar los siguientes elementos:
  • Línea de estado: Es la primera línea de la respuesta, incluye el código HTTP que retorna la respuesta del servidor así como un pequeño mensaje de el resultado (OK, Not-Found, Forbidden…) y la versión del protocolo utilizada.
  • Cabeceras de la respuesta: Contienen todas las cabeceras de la respuesta HTTP, como puede ser cookies, Servidor (indica el software y versión del servidor), Date (timestamp de la respuesta), etc.
  • Cuerpo de la respuesta: Este Apartado puede estar incluido, o no, dependiendo del código de estado HTTP de la respuesta. En caso de incluirse cuerpo de la respuesta, éste puede contener el código HTML de una página web, una imagen o un fichero binario al que hayamos solicitado acceder, e incluso mensajes estructurados como JSON o XML.

La siguiente ilustración detalla las partes de una respuesta HTTP:

Códigos de estado HTTP
Dentro del protocolo HTTP existen varios códigos de estado que pueden utilizarse en la cabecera de la respuesta que indican al navegador el resultado de su operación. Por ejemplo, indican si su operación ha tenido éxito, si se ha intentado acceder a un recurso no permitido o si se va a efectuar una redirección de la navegación. A continuación se muestra un listado de estos códigos de estado y sus

  • Códigos con estado 1xx: Respuestas informativas, indica que la petición ha sido recibida y se está procesando.
  • Códigos con estado 2xx: Respuestas que han sido procesadas correctamente y no retornan ningún tipo de error.
  • Códigos con estado 3xx: Respuestas de redirección. Indica que el cliente necesita realizar otra petición a la dirección URL indicada por el servidor en la cabecera de respuesta.
  • Códigos con estado 4xx: Errores causados por el cliente. Indica que ha habido un error en el procesado de la operación a causa de que el cliente no ha generado una petición correcta, trata de acceder a un recurso que no existe o para el que no se encuentra autorizado.
  • Códigos con estado 5xx: Errores causados por el servidor. Indica que ha habido un error en el procesado de la petición provocado por un fallo en el servidor.

Cabeceras de respuesta HTTP
Las cabeceras de respuesta HTTP indican cierta información adicional al cliente que puede utilizar para componer la próxima petición HTTP que se realice contra el mismo recurso. Se puede consultar un listado bastante completo de cabeceras en la siguiente dirección URL /https://en.wikipedia.org/wiki/List_of_HTTP_header_fields).

A continuación se muestran las cabeceras de respuesta HTTP más comunes:

  • Access-Control: Indica otros dominios que pueden compartir información con el servidor, por ejemplo si se intercambia información con Google analytics.
  • Allow: Indica los métodos HTTP soportados por el recurso remoto.
  • Cache-Control: Indica la configuración de la cache del navegador para cada recurso accedido en ese aplicativo (por ejemplo, el tiempo máximo que se ha de almacenar la respuesta en el navegador en memoria caché).
  • Content-Encoding: Indica que tipo de codificación se está aplicando en los datos incluidos en el cuerpo de la respuesta HTTP.
  • Content-Language: Indica el lenguaje utilizado para componer la respuesta (es).
  • Content-Lenght: Indica el tamaño de la respuesta en bytes.
  • Content-Type: El Tipo Mime de los datos de la respuesta (Content-Type: text/html; charset=utf-8)
  • Date: Fecha en la que se generó la respuesta HTTP.
  • Expires: Indica el tiempo en el que la respuesta deja de ser válida y se ha de descartar.
  • Last-Modified: Indica la última vez que se modificó el recurso en el servidor.
  • Location: Se utiliza en los mensajes de redirección (Código de estado HTTP 3xx) para indicar la dirección URL a la que redirigir la navegación del usuario.
  • Server: Indica el tipo y versión del Software utilizado en el servidor.
  • Set-Cookie: Establece una cookie, indicándole al usuario que la utilice en todas las peticiones HTTP sucesivas contra el mismo recurso.
  • Strict-Transport-Security: Fuerza a que el navegador del usuario únicamente se comunique con el servidor mediante el protocolo cifrado HTTP.
  • WWW-Authenticate: Indica el tipo de autenticación adicional que se ha de utilizar para acceder al recurso solicitado (Por ejemplo Autenticación Básica o Autenticación vía WebSockets)
  • X-Frame-Options: Protección especifica para evitar que la página pueda cargarse en marcos transparentes en otro dominio (Técnica utilizada en phishing)
  • X-Powered-By: Especifica la tecnología específica con la que se ha desarrollado la aplicación (X-Powered-By: PHP/5.4.0)

Tipos de autenticación web

Autenticación web
La autenticación web es el proceso de discernir si un cliente es quien dice ser en un aplicativo web determinado.

En los aplicativos web, existen distintos tipos de autenticación que enumeramos a continuación.

Autenticación basada credenciales
Es el proceso de autenticar a un usuario del aplicativo web basándose en las credenciales que el usuario dispone, normalmente un usuario y contraseña.

El usuario ha de identificarse con este usuario y contraseña en el aplicativo.

Existen varios tipos de autenticación ligada a la autenticación basada en credenciales. A continuación se enumeran los más importantes.

  • Autenticación Básica

HTTP básica es el tipo más simple de autenticación web disponible. Esta forma de autenticación solicita al usuario que inicie sesión con su nombre de usuario y contraseña. Sin embargo, la información se transmite utilizando codificación Base64 a través de una cabecera "Authorization: Basic". Esto significa que la información enviada no se cifra.

En caso de que la información fuera capturada mediante técnicas de Man in The Middle, las credenciales del usuario podrían ser accesibles. Además, esta situación se agrava debido a que las credenciales codificadas se envían en cada petición HTTP.

A continuación se muestra una cabecera de tipo Authorization Basic. Si se decodifica mediante base64 podemos comprobar que las credenciales son usuario "Aladdin" y contraseña "open sesame"

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

  • Autenticación Digest

Los protocolos de autenticación Digest funcionan de manera similar a la autenticación básica. El servidor solicita la información de identificación, que es suministrada por el usuario en la forma de un nombre de usuario y una contraseña. El servidor, a continuación, compara las credenciales con lo que está en archivo, y siempre y cuando coincidan, concederá el acceso.

La diferencia primaria con la autenticación de HTTP con protocolo Digest es que la conexión se realiza de una manera segura. Esto es debido a que las contraseñas son almacenadas en la base de datos de usuario en un formato cifrado y se transmiten a través de una cabecera "Authorization: Digest".

De esta manera, la integridad de la contraseña es mucho más segura, ya que sólo puede ser leída por el servidor web.

A continuación se muestra una cabecera Authorization Digest, en este caso no es posible revertir las credenciales de una manera directa.

GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
realm="testrealm@host.com",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"

  • Autenticación Basada en Cookies

La autenticación basada en cookies ha sido el método predeterminado (y comprobado) para manejar la autenticación de usuarios durante mucho tiempo. La autenticación basada en cookies presenta un estado de tipo "stateful".

Al iniciar sesión, a través de un formulario de autenticación en el que el usuario envía sus credenciales, el servidor registra datos con el fin de recordar que el usuario se ha identificado correctamente. Estos datos que se registran en el backend, en correspondencia con el identificador de sesión, es lo que se conoce como estado.

El aplicativo le envía al navegador el identificador de sesión generado para identificar al usuario mediante la cabecera de respuesta HTTP "set-cookie". De esta manera el navegador siempre enviará las cookies en cada petición HTTP y, con ellas, el identificador de sesión que le autentica en el aplicativo.

El flujo que sigue este sistema de autenticación tradicional es el siguiente:

  • Un usuario ingresa sus credenciales (datos que le permiten iniciar sesión)
  • El servidor verifica que las credenciales sean correctas, y crea una sesión (esto puede corresponderse con la creación de un archivo, un registro nuevo en una base de datos, o alguna otra solución server-side)
  • Una cookie con el session ID es puesta en el navegador web del usuario
  • En las peticiones siguientes, el session ID es comparado con las sesiones creadas por el servidor
  • Una vez que el usuario se desconecta, la sesión es destruida en ambos lados (tanto en el cliente como en el servidor)
  • Autenticación basada en tokens

En este método, el usuario se identifica al igual que con la autenticación básica, con sus credenciales, nombre de usuario y contraseña. Pero en este caso, con la primera petición de autentificación, el servidor generará un token basado en esas credenciales.

El servidor guarda en base de datos este registro y lo devuelve al usuario para que a partir de ese momento no envíe más credenciales de inicio de sesión en cada petición HTTP. En lugar de las credenciales, simplemente se debe enviar el token codificado en cada petición HTTP.

Por norma general, los tokens están codificados con la fecha y la hora para que en caso de que alguien intercepte el token con un ataque MiTM, no pueda utilizarlo pasado un tiempo establecido. Además de que el token se puede configurar para que caduque después de un tiempo definido, por lo que los usuarios deberán iniciar sesión de nuevo.

A continuación se muestra un ejemplo de la cabecera Authorization cuando se utilizan tokens de tipo JWT para autenticarse en el equipo.

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NGE4Y2U2MThlOTFiMGIxMzY2NWUyZjkiLCJpYXQiOiIxNDI0MTgwNDg0IiwiZXhwIjoiMTQyNTM5MDE0MiJ9.yk4nouUteW54F1HbWtgg1wJxeDjqDA_8AhUPyjE5K0U

  • API Keys

Una clave de API es un token que proporciona un cliente cuando realiza llamadas a una aplicación de tipo API para identificarse. Normalmente es un valor fijo que se entrega al usuario del aplicativo y ha de enviarlo en cada petición contra la API.

Este valor puede enviarse en la petición HTTP de varias maneras:

  • En la propia petición cómo si fuera un parámetro HTTP:

GET /something?api_key=abcdef12345

  • En una cabecera específica de la petición HTTP:
GET /something HTTP/1.1
X-API-Key: abcdef12345
  • A través de una cookie

GET /something HTTP/1.1
Cookie: X-API-KEY=abcdef12345
 

Con la autenticación de clave API, envía un par clave-valor a la API, ya sea en los encabezados de solicitud o en los parámetros de consulta. Algunas API utilizan claves de API para la autorización.

Las claves API son un secreto que solo el cliente y el servidor conocen. Al igual que la autenticación básica, la autenticación basada en claves API únicamente se considera segura si se usa junto con otros mecanismos de seguridad, como HTTPS/SSL.

Una de sus desventajas, al igual que ocurre con la autenticación de tipo "Basic" es que la API Key no suele cambiar, de tal manera que si esta clave es usurpada, el atacante podría utilizarla hasta que se forzase el cambio de la misma por parte del servidor.

Autenticación basada en certificado
Es el proceso de autenticar a un usuario en el aplicativo mediante un certificado de cliente que el usuario posee.

Por ejemplo, es el método más común para autenticarse en los aplicativos web de la administración pública. En los cuales el usuario ha de verificar su identidad mediante un certificado personal emitido por la FNMT o, en su defecto, mediante el certificado que incorpora el DNI electrónico.

Autenticación múltiple o de doble factor
La autenticación doble, o verificación en dos pasos, es una capa adicional de seguridad que complementa el uso de una contraseña. Su objetivo es el de asegurarse de que el usuario no solo conoce la contraseña para acceder al servicio, sino que además es quien dice ser aportando en el proceso de logueo información, un código por ejemplo, sobre algo que solo él posee. Dicha información puede obtenerla de la siguiente forma:

  • A través de una llamada de teléfono o SMS enviado por el servicio.
  • Haciendo uso de una tarjeta inteligente (token) física o virtual.
  • Utilizando un dispositivo biométrico.

Este tipo de autenticación puede presentarse tanto a la hora de autenticar a un usuario en el sistema, como a la hora de requerir una autenticación adicional para realizar algún tipo de tarea privilegiada.

Pruebas de recolección de información
Existen distintas pruebas que podemos realizar para recopilar información específica sobre los aplicativos a auditar y la infraestructura que los sustenta.

Como podréis comprobar, muchas de las pruebas que se aplican son las mismas que podríamos aplicar en las fases de reconocimiento y escaneo, pero esta vez enfocadas a recopilar información del aplicativo e infraestructura.

A continuación, se muestran las pruebas más comunes para recopilar este tipo de información.

Fuga de información utilizando motores de búsqueda
Este conjunto de pruebas trata de obtener más información del aplicativo a auditar haciendo uso de motores de Búsqueda públicos (Google, Bing, Censys, archive.org, pastebin, Shodan…). Las técnicas a utilizar se corresponden con las técnicas vistas en entradas anteriores en las cuales se obtenía información del objetivo utilizando estos motores de búsqueda.

Merece la pena recordar los buscadores más utilizados:

  • Google: Uno de los buscadores más utilizados, tiene numerosos operadores de búsqueda para realizar búsquedas avanzadas.
  • Bing: Buscador de Microsoft. La principal diferencia de este buscador con los demás es que permite realizar búsquedas basadas en direccionamiento IP.
  • DuckDuckGo: Al igual que google, también permite utilizar operadores avanzados de búsqueda.
  • Shodan: Es un buscador que en vez de indexar páginas web indexa tecnologías y servicios publicados en internet, pudiendo realizar búsquedas por una versión concreta de un determinado software, o por todas las tecnologías de una determinada organización, etc.
  • Censys: Este buscador parecido a shodan se utiliza principalmente para buscar dominios que compartan el mismo certificado, o que tengan ciertos datos en el certificado expedido (Empresa, dominio, etc.)
  • Archive.org: Este buscador tiene indexadas versiones antiguas de las páginas a lo largo de varios años. De esta manera podremos comprobar tecnologías que se estuvieran utilizando, parámetros de entrada o páginas que aunque no se encuentren enlazadas puedan estar presentes, etc.

Fuga de información en metadatos, ficheros de servidor y comentarios
El objetivo de estas pruebas es identificar información, que nos pueda ser de utilidad, en metadatos de ficheros (Por ejemplo en los metadatos de los documentos ofimáticos se puede encontrar nombres de usuario y versión del software utilizado para generarlo).

Por otro lado, también se recomienda mirar los comentarios que dejan los desarrolladores en ficheros HTML o JavaScript por si han dejado información que pudiera ser interesante en estos comentarios.


Por último, se recomienda siempre revisar el fichero robots.txt de cada dominio (http://www.prueba.es/robots.txt). Este fichero se incluye en la raíz de cada dominio para evitar que los motores de búsqueda indexen contenido de las rutas indicadas en el fichero. En ciertas ocasiones podemos apreciar nuevas rutas que no están referenciadas en la aplicación (por ejemplo, paneles de administración).

Identificar el servidor web
Identificar el tipo de servidor web, y su versión, utilizado para sustentar el aplicativo web. Este tipo de información nos ayuda a detectar vulnerabilidades conocidas que puedan afectar a la versión del servidor utilizado.

En algunas ocasiones la respuesta HTTP devuelta por el servidor contiene una cabecera específica “Server” que indica el tipo de servidor utilizado y, en ciertas ocasiones, también la versión del mismo.

Además, al igual que vimos en entradas anteriores, es posible obtener esta información utilizando herramientas como nmap o nessus, que identifican el servidor en el caso que se muestre esta información en la respuesta HTTP o incluso analizando el tipo de respuestas devueltas.

Identificar aplicativo web o framework utilizado
Parecido al caso anterior, pero esta vez tratamos de comprobar si el aplicativo a analizar se ha realizado tomando como base una aplicación web conocida (Por ejemplo, gestores de contenido, foros, blogs, wiki, etc.). Una vez se dispone de esta información, se puede comprobar si la versión utilizada presenta algún tipo de vulnerabilidad conocida.

De manera similar, si la aplicación se ha desarrollado en base a un determinado framework de programación, también es interesante intentar obtener el framework y versión utilizada dado que también puede ser susceptible a presentar vulnerabilidades “públicas”.

Para poder obtener esta información se recomienda revisar y analizar las respuestas HTTP devueltas por el servidor dado que esta información puede encontrarse tanto en las cabeceras como en el cuerpo de las respuestas HTTP.

Herramientas de recolección de información
Para poder recopilar la información que necesitamos del aplicativo o de su infraestructura nos apoyamos en distintas herramientas que nos facilitan la tarea. Muchas de ellas ya las vimos previamente en la fase de escaneo y otras son herramientas que no habíamos visto con anterioridad dado que son herramientas que únicamente se utilizan en el ámbito web. 

Herramientas generales
Gracias a este tipo de herramientas podemos recopilar información específica del aplicativo e infraestructura sin que las pruebas estén adaptadas a ningún aplicativo, framework o infraestructura concreta.

  • nc

También conocido como netcat, nc es una herramienta de red que permite, a través de intérprete de comandos y con una sintaxis sencilla, abrir puertos TCP/UDP en un HOST (quedando netcat a la escucha), asociar una shell a un puerto en concreto (para conectarse por ejemplo a MS-DOS o al intérprete bash de Linux remotamente) y forzar conexiones UDP/TCP (útil por ejemplo para realizar rastreos de puertos o realizar transferencias de archivos bit a bit entre dos equipos). Posteriormente fue portada a Windows y Mac OS X entre otras plataformas.

Para poder realizar la conexión simplemente habrá que indicar la dirección IP y el puerto al que se ha de conectar.

$ nc dirección_ip puerto

Una vez realizada la conexión, si queremos que el servidor devuelva el banner del servicio habrá que transmitir datos con la conexión establecida. En el caso de realizar una petición HTTP, el servidor web devolverá la respuesta HTTP en la que podremos comprobar si en las cabeceras de respuesta se puede obtener algún dato del aplicativo o servidor remoto.

  • BurpSuite

BurpSuite es uno de los proxies de interceptación HTTP más utilizados. Podemos utilizarlo para inspeccionar las cabeceras de respuesta HTTP al igual que lo hemos hecho con nc.

También podemos utilizar la herramienta a modo de escáner pasivo. La herramienta incorpora varios plugins que realizan ciertas pruebas. Varios de estos plugins inspeccionan las respuestas provenientes del servidor para localizar versiones de aplicativo, versiones de servidor, framework utilizado. o incluso información sensible en comentarios o devuelta en el propio código de la aplicación.

  • Whatweb

WhatWeb es una herramienta que trata de identificar todos los componentes y tecnologías utilizados por un aplicativo web.

El funcionamiento consiste en realizar un proceso de spidering (recorre toda la web) y luego analiza toda la información devuelta por el aplicativo.

Dispone de cerca de 1800 plugins distintos para realizar esta tarea de análisis de información.

Herramientas específicas
Existen ciertas herramientas que nos ayudan a recopilar información en ciertos frameworks muy específicos. Todas las herramientas presentadas ya las vimos para realizar una búsqueda de vulnerabilidades. Pero dado que primero realizan una verificación de las versiones de los aplicativos y frameworks utilizados, así como de los módulos y librerías utilizados también nos proporcionan la información que necesitamos.

  • Nessus

Como ya pudimos comprobar, Nessus es la aplicación de escaneo de vulnerabilidades más conocida y utilizada. Podemos utilizarla también sobre un determinado aplicativo y realizará una recopilación de información, tanto del aplicativo como de su infraestructura, además de indicar las posibles vulnerabilidades existentes dependiendo de las versiones.

  • CMSMap

Escáner “open source” desarrollado en Python que localiza vulnerabilidades en los CMS (sistema de gestión de contenidos) más populares como son Wordpress, Joomla, Drupal y Moodle. En este caso también se puede utilizar para la recopilación de información dado que es capaz de enumerarte módulos utilizados y versiones de los mismos.

  • JoomScan

Escáner “open source” desarrollado en perl y perteneciente al proyecto OWASP. Localiza vulnerabilidades de versión y defectos en la configuración de portales basados en el framework Joomla. En este caso también se puede utilizar para la recopilación de información dado que es capaz de enumerarte módulos utilizados y versiones de los mismos.

  • Wpscan

Escáner “open source” desarrollado en Ruby. Localiza vulnerabilidades de versión y defectos en la configuración de portales basados en el framework WordPress. En este caso también se puede utilizar para la recopilación de información dado que es capaz de enumerarte módulos utilizados y versiones de los mismos, usuarios, incluso permite ataques de fuerza bruta para obtener sus contraseñas.

Antes de nada, es importante comentar que si se desea que wpscan haga un análisis de vulnerabilidades, es necesario suministrar una API KEY (https://wpscan.com/register), que se obtiene tras registrarse en la web de la herramienta, Una vez registrado, se puede acceder a ella en la página de perfil (/profile).

Las opciones principales son:

  • --url: dirección url.
  • --api-token TOKEN: necesaria para que wpscan haga un análisis de vulnerabilidades.
  • -v, --verbose: para que la salida muestre más mensajes de retroalimentación.
  • -e, --enumerate [opciones]: para enumerar distintos elementos. La lista de opciones posible es (se pueden indicar varias opciones separadas por comas):
    • -vp: plugins vulnerables.
    • -ap: todos los plugins.
    • -vt: temas vulnerables.
    • -at: todos los temas.
    • -cb: config backups.
    • -u: usuarios.
  • -P, --passwords: diccionario de contraseñas para extraer credenciales de los usuarios.
  • -U, --usernames: permite suministrar una lista de usuarios (separados por comas) o un fichero con nombres de usuarios para tratar de extraer credenciales.

Búsqueda de vulnerabilidades habituales en aplicativos web
La auditoría de aplicativos web absorbe la mayor parte de los proyectos relacionados con la seguridad ofensiva y el hacking ético. Si bien es cierto que de los últimos años a esta parte también se están realizando numerosos ejercicios de otra índole como los test de intrusión internos/externos o los ejercicios de RedTeam. La búsqueda de vulnerabilidades en aplicativos web sigue siendo uno de los proyectos más demandados por las compañías.

Por esta razón, el siguiente subapartado discurre enumerando las distintas pruebas más importantes que se han de realizar a la hora de realizar una auditoría de aplicativo web.

Para ello, utilizaremos la agrupación que recoge la Guía de pruebas en aplicativos web de la fundación OWASP.


Fundación OWASP
La fundación OWASP es un organismo sin ánimo de lucro cuya misión es mejorar el nivel de seguridad en el software en general y de los aplicativos web/móvil en particular. Para ello aporta a la comunidad numerosas guías educativas y herramientas para incrementar el nivel de seguridad de este tipo de aplicativos.

Por un lado, mediante los diferentes recursos proporcionados por OWASP, los desarrolladores mejoren el nivel de seguridad de sus aplicaciones aplicando buenas prácticas en el desarrollo de los aplicativos.

Por otro, los auditores o pentesters también pueden hacer uso de sus guías y metodologías para realizar las pruebas de seguridad sobre un determinado aplicativo, así como utilizar las herramientas open source que ofrece la organización.

Los proyectos más destacados de la fundación OWASP son los siguientes:

  • OWASP Web Security Testing Guide

Guía especializada que nos indica como afrontar una revisión de seguridad en un aplicativo web. Contiene los conceptos básicos de este tipo de auditorías, así como un resumen y catalogación de las vulnerabilidades más comunes en este tipo de aplicativos. Además, para cada vulnerabilidad incluida se incluye la metodología y pruebas necesarias para comprobar si la vulnerabilidad se encuentra presente en el aplicativo, así como recomendaciones para solucionar la vulnerabilidad.

  • OWASP Mobile Security Testing Guide

Similar al anterior, pero orientado a las auditorías de aplicativos móviles. Contiene los conceptos básicos de este tipo de auditorías, así como un resumen y catalogación de las vulnerabilidades más comunes en este tipo de aplicativos. Además, para cada vulnerabilidad incluida se incluye la metodología y pruebas necesarias para comprobar si la vulnerabilidad se encuentra presente en el aplicativo así como recomendaciones para solucionar la vulnerabilidad.

Dado que la comunicación que se realiza entre el aplicativo móvil y el servidor se realiza mediante tecnologías propias de un aplicativo Web (normalmente la comunicación se realiza mediante el uso de API web) la guía se centra más en vulnerabilidades dependientes de la plataforma (Android e iOS) y para las vulnerabilidades que pudieran afectar al servidor nos apoyaríamos en la “Web Security Testing Guide”

  • Zed Attack Proxy (ZAP)

Como desgranamos en la siguiente entrada, ZAProxy es un aplicativo tipo proxy web open source utilizado para realizar las pruebas necesarias para comprobar la existencia de las vulnerabilidades descritas en la guía “Web Security Testing Guide”.

  • OWASP Top Ten – OWASP Mobile Top Ten

Proyecto que identifica y clasifica las vulnerabilidades más críticas que pueden producirse en los aplicativos web y aplicativos móviles respectivamente.

  • OWASP Code Review Guide

Guía especializada que contiene un conjunto de “Mejores prácticas de programación” para evitar introducir vulnerabilidades, de tipo web, a la hora de desarrollar los aplicativos.

Pruebas de configuración y despliegue
Este conjunto de pruebas trata de identificar cierto tipo de vulnerabilidades que se producen debido a realizar una configuración incorrecta, o no adecuada, en los sistemas. A continuación se muestran las pruebas más representativas de esta categoría:

  • Paneles de administración expuestos

En ciertas ocasiones los aplicativos web disponen de un acceso administrativo a través de un panel de administración, el cual permite realizar acciones privilegiadas dentro de la aplicación. En algunos casos, estas interfaces de administración no disponen de los controles de protección necesarios y son susceptibles de presentar vulnerabilidades que pudieran ocasionar un acceso no permitido.

Este tipo de pruebas tratan de descubrir paneles de administración que puedan ser accesibles de manera pública en internet.

Para poder comprobar si existe un panel de administración expuesto podemos hacer uso de las siguientes técnicas:

  • Enumeración de ficheros y directorios (fuerza bruta con listado de posibles paths de administración).
  • Búsqueda de paneles de administración en motores (Google Dorks).
  • Buscar urls y enlaces en el código fuente del aplicativo (html y JavaScript).
  • Si el aplicativo tiene como base una aplicación conocida o está desarrollado en un framework específico es posible consultar la documentación para comprobar si existe algún acceso administrativo por defecto.
  • Comprobar si existe algún panel de administración en algún otro puerto TCP que preste servicio bajo los protocolos HTTP/HTTPS.
  • Acceso a ficheros expuestos o no referenciados

De la misma manera, también se puede dar el caso de acceder a ciertos ficheros no referenciados por la aplicación (mediante funcionalidades directas o hipervínculos), pero que pertenezcan a la misma y se encuentren accesibles de manera pública. Por ejemplo, ficheros de Backup de versiones anteriores de la aplicación, ficheros de logs, ficheros de configuración que muestren información sensible en los parámetros de configuración e incluso credenciales de autenticación para interconectar distintos componentes de la aplicación (Gestores de Identidad, Bases de Datos, etc.).

Las siguientes técnicas nos pueden ser de utilidad para localizar este tipo de ficheros. Como se puede comprobar, muchas de las técnicas ya han sido descritas y únicamente habrá que modificar el enfoque de la información a buscar.

  • Enumeración de ficheros y directorios (fuerza bruta con listado de posibles paths y nombres y extensión de ficheros).
  • Búsqueda de ficheros específicos (como los ya mencionados) en motores (Google Dorks).
  • Buscar urls y enlaces en el código fuente del aplicativo (html y JavaScript).
Pruebas de gestión de identidad
Este tipo de pruebas comprueban si existe una gestión adecuada de la identidad de los usuarios, si los usuarios disponen de un rol de acceso y de autorización adecuado. Además, también incluyen todas las pruebas relacionadas con la posibilidad de enumerar o averiguar nombres de cuentas de usuario o sus direcciones de correo electrónico.
  • Gestión de roles
Para evitar tener que conceder permisos y/o privilegios de manera individual a cada usuario, los aplicativos web integran el concepto de gestión de roles. Mediante este tipo de gestión se otorgan ciertos permisos a cada rol del aplicativo (usuario, operador, supervisor, administrador, etc.) y luego estos roles son aplicados a los usuarios.
 
Las pruebas de gestión de roles tratan de comprobar si estos roles se han definido de manera satisfactoria y un determinado rol no tiene más privilegios de los permitidos (por ejemplo que un operador pueda realizar ciertas operaciones propias de un administrador).
  • Enumeración de usuarios
Este tipo de pruebas tratan de comprobar si abusando de las funcionalidades de la aplicación es posible acceder a un listado de cuentas de usuario o a las direcciones de correo asociadas a estas cuentas. Por otro lado, también trata de averiguar si un determinado usuario, o cuenta de correo electrónico, se encuentra presente en el sistema (o no) atendiendo a las respuestas de error producidas en el formulario de acceso, en el formulario de registro de nuevo usuario, o en el formulario de reset de contraseña.

Pruebas de autenticación
Este tipo de pruebas tratan de comprobar el correcto funcionamiento de todas las partes del aplicativo involucradas en el proceso de autenticación. Es decir, que se pueda verificar que un usuario es quien dice ser. Además, también comprueba si es posible recuperar o acceder a las credenciales de un usuario legítimo de la aplicación.
 
Evasión del proceso de autenticación
Este control determina si es posible evadir el proceso de autenticación de un aplicativo web, y acceder a su parte privada, sin necesidad de autenticarnos mediante el uso de unas credenciales de usuario legítimas. Existen varias técnicas para realizar este proceso.
 
Cabe destacar que a día de hoy resulta poco frecuente poder realizar una evasión del proceso de autenticación debido al nivel de madurez de los aplicativos web. A continuación se exponen las más comunes:
  • Acceso directo a la parte privada
Esta técnica consiste en acceder directamente a las direcciones URL de la parte privada del aplicativo sin necesidad de haber realizado una autenticación en el sistema. A día de hoy, es difícil que un aplicativo web se vea afectado en su totalidad por esta vulnerabilidad. Sin embargo, podemos encontrar alguna dirección URL perteneciente a la página a la cual se accede sin necesidad de autenticación.
  • Modificación de parámetros
En algunos aplicativos webs puede existir un parámetro web que indique si el usuario se encuentra autenticado en la aplicación (o no) y dependiendo del valor de ese parámetro, el aplicativo puede saber si el usuario se ha autenticado correctamente en la plataforma.
  • Predicción del identificador de sesión
Dado que lo más común es manejar el estado de la sesión mediante identificadores de sesión (normalmente transmitidos a través de las cookies o cabeceras especiales). Si la generación de estos identificadores de sesión no es completamente aleatoria, un atacante podría predecir el identificador de sesión de un usuario legítimo de la aplicación que se encuentre en uso.
  • Inyección SQL en el formulario de acceso a la aplicación
Es la técnica que más éxito tuvo en el pasado. Su funcionamiento radica en que la funcionalidad de autenticación de un usuario se realiza mediante un formulario en el que el usuario introduce sus credenciales y estas credenciales son validadas en la Base de Datos del aplicativo.
 
Debido a que el nivel de madurez en materia de seguridad de los aplicativos era bastante bajo, por norma general, no existía ningún proceso que validase los datos introducidos por el usuario (eliminar los caracteres especiales y comandos específicos SQL) previamente a su uso por el motor de Base de Datos. De esta manera, los atacantes podrían inyectar código SQL específico que pudieran ser interpretados por la Base de Datos y generar una consulta distinta.
Por ejemplo, la consulta SQL que realizaría de manera interna el aplicativo sería la
siguiente: 
 
SELECT * FROM login WHERE username=’usuario’ and password=’contraseña’

La siguiente inyección en el formulario de acceso generaría la siguiente consulta 
 
SELECT * FROM login WHERE username=’usuario’ and password=’contraseña’ OR 1=1 -- ’
 

De esta manera la consulta SQL resultante devolvería resultados si el nombre de usuario es correcto y si la contraseña introducida es correcta o no siempre y cuando 1=1. Dado que la inyección introducida 1=1 siempre es una condición verdadera, no es necesario que indiquemos la contraseña del usuario, dado que el motor de la Base de Datos validará la segunda condición y nos autenticaremos suplantando la identidad del usuario que hubiéramos especificado en el parámetro “username”.
 

Credenciales enviadas por un canal sin cifrar
Cualquier protocolo que transmita información sin cifrar el canal de comunicaciones es susceptible exponer la información que transmiten en caso de producirse un ataque de tipo Man in The Middle. En el caso de los aplicativos web, se podrían capturar las credenciales que le identifican en la aplicación (además de otra información sensible del usuario).

Además del ejemplo expuesto, existen otras casuísticas que pueden permitir la exposición de las credenciales de usuario en texto claro:

  • Uso del protocolo HTTP
Como hemos indicado este protocolo transmite la información por un canal sin cifrar, de manera que cualquier atacante que intercepte la comunicación (o tenga acceso a dispositivos intermedios como proxies o dispositivos de red) puede capturar las credenciales de un usuario.
  • Aplicativo disponible bajo HTTP y HTTPS
En caso de que el aplicativo se encuentre prestando servicio bajo los protocolos HTTP (sin cifrar) y HTTPS (Cifrado). Aunque un usuario esté accediendo al aplicativo a través del protocolo HTTPS, un atacante que pudiera realizar un ataque de tipo Man in The Middle podría forzar la transmisión de las credenciales mediante el protocolo HTTP, de manera totalmente transparente al usuario, dado que el aplicativo lo permite. Este ataque se conoce como SSLStrip attack (https://moxie.org/software/sslstrip/).
  • Envío de la información mediante el protocolo cifrado HTTPS pero con el método GET

El método HTTP GET se caracteriza por que no dispone de cuerpo de la petición HTTP y los parámetros necesarios son transmitidos en la propia dirección URL. En el caso de que se esté enviando la información a través del protocolo cifrado HTTPS, la información transmitida se encontrará protegida ante ataques de tipo Man in The Middle. Sin embargo, al transmitirse esta información en la propia URL queda expuesta en el historial del navegador web utilizado y en los log del servidor web que sustenta el aplicativo.

La siguiente ilustración muestra la captura de una petición transmitida por HTTPS pero que expone las credenciales del usuario en la propia dirección URL:

Uso de credenciales por defecto
En ocasiones ciertos aplicativos web toman como base para su desarrollo aplicativos conocidos, tanto open source como software comercial. Este tipo de software puede incluir ciertas cuentas habilitadas por defecto para poder desplegar el aplicativo. Además, estas cuentas también suelen presentar contraseñas por defecto que son conocidas y se encuentran disponibles en los manuales de la aplicación base utilizada.

En caso que los administradores del aplicativo no hayan modificado las credenciales de estas cuentas por defecto, un atacante podría acceder al aplicativo utilizando estas cuentas que suelen ser cuentas de administración o similar.

Para poder comprobar el uso de credenciales por defecto podemos utilizar las siguientes técnicas:

  • Realizar búsquedas específicas en internet para averiguar las credenciales por defecto de los aplicativos afectados.
  • Realizar búsquedas en los manuales del aplicativo base o en el repositorio del mismo (en caso de ser un aplicativo open source).
  • Utilizar diccionarios de credenciales por defecto junto con una herramienta de fuerza bruta (el propio proxy de interceptación Burp Suite te permite automatizar esta tarea).

Funcionalidad de recordatorio de contraseñas vulnerable
Los aplicativos web suelen incluir una funcionalidad de recordatorio o reset de contraseñas de un usuario. De esta manera, en caso que el usuario no recuerde la contraseña utilizada en el aplicativo podrá cambiarla de una manera cómoda. Sin embargo, si esta funcionalidad no implementa las medidas de protección adecuadas puede dar lugar a un vector de ataque que puede ser utilizado para acceder a la aplicación suplantando la identidad de un usuario legítimo de la aplicación. Existen varias pruebas que han de realizarse para cerciorarse que esta vulnerabilidad de recordatorio de contraseña no supone ningún tipo de amenaza contra el aplicativo:

  • Comprobar la información que se requiere para resetear la password
Se ha de comprobar si para resetear la contraseña se solicitan al usuario ciertos datos que únicamente pertenezcan al usuario (por ejemplo, una dirección de correo electrónico) y algún dato que únicamente el usuario conozca (lo que se conoce como pregunta secreta) hay que cerciorarse que esta información secreta no se encuentra disponible en sitios públicos como redes sociales o similar.
  • Comprobar cómo se comunica la nueva contraseña al usuario
A continuación, se exponen los casos más comunes de menos seguro a más seguro:
  • Al resetear la contraseña se muestra directamente al usuario la nueva contraseña para autenticarse.
  • Se establece una contraseña temporal y se fuerza al usuario a modificarla en el siguiente inicio de sesión.
  • Se envía un correo electrónico al usuario con un enlace para realizar el cambio de contraseña.
  • Política de contraseñas débil
Comprobar que el aplicativo web ha de tener una política de contraseñas lo suficientemente robusta que fuerce al usuario a establecer una contraseña lo suficientemente compleja para que no sea fácilmente adivinable.
  • Combinar Mayúsculas, minúsculas, números y caracteres especiales.
  • Longitud mínima de 8 caracteres.
  • No debe contener ningún dato del usuario (username, nombre, apellidos)
  • En la medida de lo posible, que no utilice palabras de uso común (no siempre es posible)
Pruebas de autorización
Las pruebas de autorización comprueban el correcto funcionamiento de todas las partes del aplicativo involucradas en el proceso de autorización de acceso a recursos y funcionalidades de la aplicación. Es decir, que se pueda verificar que un determinado usuario únicamente dispone de acceso a los recursos e información que le pertenecen así como a las funcionalidades del aplicativo propias del nivel de acceso del usuario.
 
Path y Directory traversal
Esta vulnerabilidad se produce cuando la propia aplicación gestiona ficheros y/o utiliza los mismos como valor de entrada para alguna funcionalidad. Por ejemplo, subida de ficheros, visualización de ficheros etc.
 
En caso de no validar correctamente los datos de entrada introducidos en la aplicación, un atacante puede modificar el path del fichero a visualizar para acceder a otro documento del aplicativo o del sistema. Incluso, algunas ocasiones, poder ejecutar comandos remotos en el sistema afectado.
 
Por ejemplo, la siguiente captura evidencia que el aplicativo muestra ciertos documentos atendiendo al valor del parámetro file de la propia dirección URL. Al modificar el valor del parámetro “file” por un fichero del sistema, el contenido del fichero solicitado se muestra en el aplicativo (siempre que el usuario con el que se inicia el servidor web disponga de privilegios para ello).


Evadir el sistema de autorización
Este tipo de pruebas tratan de comprobar si es posible acceder a un determinado recurso o funcionalidad del aplicativo al cual no deberíamos poder acceder con el usuario utilizado. Se recomienda revisar las siguiente casuísticas:
  • Comprobar si se puede acceder a un determinado recurso, aunque no se haya realizado el proceso de autenticación o nos hayamos autenticado con un usuario que no debería tener privilegios de acceso al recurso indicado.
  • Comprobar si se puede acceder a una determinada funcionalidad del aplicativo, aunque no se haya realizado el proceso de autenticación o nos hayamos autenticado con un usuario que no debería tener privilegios de acceso a la funcionalidad indicada.
Pruebas de elevación de privilegios
Este tipo de pruebas tratan de elevar los privilegios o los roles que el usuario tiene en un determinado aplicativo, con la intención de acceder a funcionalidades y recursos que requieran un nivel de acceso más privilegiado.
 
El tipo de pruebas a realizar dependerá en gran medida del tipo de aplicativo, tecnología y lenguaje de desarrollo utilizado. Sin embargo, esta vulnerabilidad rara vez se encuentra presente en los aplicativos web. Algunas de las técnicas a utilizar son las siguientes:
  • Manipulación del grupo de usuario
En algunos casos los aplicativos asocian al usuario un grupo o rol que se les indica a través de un parámetro HTTP, por lo que el valor puede ser modificado por el usuario para intentar otorgarse otro nivel de privilegios.

  • Manipulación de la dirección IP de origen
De manera similar, existen aplicaciones que otorgan un nivel de privilegios distinto en caso de que el acceso se realice desde una dirección IP en concreto (por ejemplo desde el rango de IP de una VPN de Administración que haya configurado la compañía o desde determinadas direcciones IP de la red local). Para ello la aplicación recoge el valor de una determinada cabecera HTTP “X-Forwarded-For”, la cual puede ser modificada por el usuario para que el aplicativo crea que el acceso se realiza desde la IP indicada.
  • Referencias inseguras a objetos de manera directa (IDOR)
Este tipo de vulnerabilidades se producen cuando la aplicación proporciona acceso a ciertos objetos o recursos, de manera directa, mediante el valor de un determinado parámetro. Por ejemplo, modificando el valor de un parámetro que indique el identificador de otro usuario, o modificando el valor de un parámetro que identifique un recurso que pertenezca a otro usuario (por ejemplo el identificador de un determinado contrato en la plataforma).
 
 
Para poder realizar este tipo de pruebas, lo ideal es contar con dos usuarios para poder conocer en identificador de los recursos de uno de ellos y tratar de acceder a estos recursos habiéndonos identificado con el otro usuario.

Gestión de sesiones
Tal y como avanzamos en apartados anteriores, el protocolo HTTP/HTTPS es un protocolo de comunicación no orientado a la conexión. Para suplir esta carencia y poder identificar las peticiones de cada usuario legítimo de la aplicación, es necesario enviar al usuario un identificador de la sesión (un ticket que identifica de manera inequívoca al usuario en la aplicación) una vez se ha autenticado. Normalmente este identificador se envía en cada petición HTTP del usuario a través de las cookies o de una cabecera específica.
 
Este tipo de pruebas tratan de comprobar si existe algún defecto en la configuración o en la manera en la que la aplicación gestiona las sesiones del usuario para identificar al usuario en el aplicativo.
 
Atributos de las cookies de sesión
En caso de que el identificador de sesión del usuario se envíe a través de las cookies, se ha de comprobar que éstas cuentan con todos los atributos de seguridad habilitados para proteger este identificador de que pueda ser robado. Estos atributos se especifican en el momento en el que se genera la cookie (A través de la cabecera de la respuesta HTTP "set-cookie") y se transmiten, al navegador del usuario, en la cabecera “set-cookie” de la respuesta HTTP enviada por el servidor. A continuación, se enumeran los atributos más comunes que se han de comprobar:
  • Secure: Atributo que fuerza al navegador del usuario a transmitir la cookie únicamente a través del protocolo HTTPS. De esta manera se evita que se pueda forzar al usuario a transmitir esta cookie mediante HTTP y que pueda ser interceptada mediante ataques de Man in The Middle (ataque ssl-strip).
  • HttpOnly: Atributo que especifica que la cookie no puede ser transmitida a través de scripts de cliente. Es decir, no se puede extraer la cookie a través de ordenes JavaScript y por tanto no se podría robar el identificador de sesión utilizando ataques de tipo Cross Site Scripting (este tipo de ataques se detallarán más adelante)
  • Domain: Atributo que indica el dominio en el cual la cookie es válida y por lo tanto a los dominios a los que será enviada la cookie. Por ejemplo, si nuestro aplicativo se encuentra en un dominio de tipo cloud como azure https://www.mi_applicacion.azure.com si restringimos el dominio de nuestra cookie de sesión a todo el dominio *.azure.com obligaremos al navegador del usuario a entregar este identificador de sesión a cualquier aplicación dentro del dominio azure.com. En caso que el usuario visitara algún otro aplicativo alojado en el dominio de Azure también se transmitiría el identificador de sesión de nuestro aplicativo al aplicativo de otro dominio.
  • Path: Muy similar al atributo anterior, pero en este caso se restringe el path en el cual la cookie es utilizada. Por ejemplo, es muy común en cierto tipo de ISP gratuitos que te ofrecen un alojamiento web en un determinado path del dominio del ISP. Por ejemplo https://sites.ucm.es/aplicativo en este caso cada departamento de la universidad tiene un path distinto en el que cuelgan su aplicativo web. En caso de no restringir el path al correspondiente al de nuestro aplicativo estaremos enviando nuestra cookie (con nuestro identificador de sesión) a cualquier aplicativo dentro del dominio sites.ucm.es (o incluso ucm.es dependiendo del valor del atributo domain), pero no a otros dominios con el mismo path.
  • Expires: Indica la fecha en la cual el navegador del usuario deja de utilizar esta cookie. Es una manera de eliminar la cookie de la caché del navegador, aunque si el servidor tiene un tiempo de validez del identificador de sesión más amplio, el identificador seguiría siendo válido, lo único que el navegador del usuario legítimo ya habría descartado ese identificador de sesión y no lo enviaría a la aplicación.
Validación del tiempo de la sesión
Este tipo de pruebas tratan de conocer el rango de tiempo que un identificador de sesión es válido en el servidor. Como hemos visto en el apartado anterior, expires sólo controla el tiempo que el navegador del usuario mantiene la cookie en la caché. Pero si un atacante ha conseguido robar el identificador de sesión previamente, podría utilizarlo para suplantar la identidad del usuario legítimo en el servidor mientras que el identificador de sesión sea válido en el servidor. Se recomienda que el identificador de sesión tenga una validez en el servidor de entre 15 – 60 minutos.
 
Para realizar esta prueba basta con acceder a un recurso utilizando un identificador de sesión que se haya utilizado tiempo atrás.
 
Incorrecto cierre de sesión
De manera similar al anterior, en este caso el problema radica en que cuando el usuario cierra la sesión (mediante la funcionalidad de cierre de sesión) el servidor no invalida el identificador de sesión utilizado por el usuario y podría seguir siendo válido en la aplicación hasta que su tiempo de vida caduque en el servidor.
 
La manera de comprobar esta situación es cerrar la sesión del usuario en el aplicativo y probar a acceder a un recurso legítimo del usuario con el identificador de sesión que tenía antes de cerrar la sesión.
 
Validación de los puntos de entrada
Este tipo de vulnerabilidades se producen debido a que los aplicativos web utilizan en muchas funcionalidades los datos proporcionados por los usuarios como datos de entrada, para realizar operaciones internas, y devolver un resultado coherente. Por ejemplo, en un buscador de productos, el buscador realiza internamente una búsqueda en la Base de Datos del valor del parámetro de búsqueda introducido por el usuario y, en consecuencia, le devuelve el resultado obtenido.
 
Si no se realiza una validación previa, de los valores de entrada proporcionados por el usuario, estos datos podrían interferir en las consultas internas realizadas alterando la ejecución de los procesos internos del aplicativo y por lo tanto el resultado esperado.
 
Atendiendo al objetivo de estas vulnerabilidades, se pueden identificar ataques dirigidos a clientes (afectan a los usuarios del aplicativo) o ataques dirigidos al servidor (afectan al propio servidor).

Vulnerabilidades que impactan en el servidor
 
Inyección SQL
Este tipo de vulnerabilidades afectan al servidor. Se trata de inyecciones de código cuya finalidad es inyectar código SQL en el aplicativo, a través de los parámetros de entrada de la aplicación proporcionados por el usuario.
 
De esta manera un atacante trata de inyectar porciones de código SQL, debidamente manipulado, para modificar la consulta SQL que la aplicación realiza de manera interna a través de una determinada funcionalidad. Si la aplicación no realiza una correcta validación de los datos del usuario (para eliminar caracteres especiales y órdenes específicas del lenguaje SQL) previo a utilizar estos parámetros como datos de la consulta, la aplicación podría ser vulnerable a ataques de inyección SQL.
 
Supongamos un aplicativo de venta online, el cual permite buscar productos en base a una determinada categoría. La dirección URL que envía el navegador del usuario para gestionar la consulta de todos los productos con la categoría “Gifts” es la siguiente:

https://insecure-website.com/products?category=Gifs
 
Cuando el aplicativo recibe la petición del usuario (para poder devolverle el resultado de los productos que ha consultado) internamente la aplicación realiza una consulta a la Base de Datos. Por su parte, el motor de Base de Datos evalúa la respuesta y devuelve el nombre y la descripción de todos los productos que pertenezcan a la categoría “Gifts”. Esta consulta tiene la siguiente sintaxis:

SELECT name, description FROM products WHERE category='Gifs'
 
En caso de que no se esté realizando una correcta validación de los parámetros de entrada del usuario, antes de ser utilizados en la consulta SQL, un usuario podría inyectar código SQL especialmente diseñado para modificar la consulta realizada y extraer más datos de la Base de Datos. A continuación se muestra un ejemplo de inyección SQL.
 
‘ UNION SELECT username, password FROM users --
 
El código inyectado modifica la consulta realizada por el controlador al motor de base de datos. La ejecución de la consulta fuerza a añadir al final de los resultados de los productos el nombre de usuario y la contraseña de todos los usuarios presentes en la tabla "users".

SELECT name, description FROM products WHERE category='Gifs' UNION SELECT username, password FROM users --'
 
Para poder encadenar dos consultas distintas mediante el operador UNION. Las dos consultas han de devolver el mismo número de columnas.

Para poder determinar el número de columnas que devuelve el resultado de la consulta original. Existen dos técnicas distintas.

Inyectar en la consulta una cláusula de ordenación por número de columna

‘ ORDER BY 1--
‘ ORDER BY 2--

 
Inyectar en la consulta una cláusula UNION SELECT incrementando el número de columnas hasta que el aplicativo no genere un error
 
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--

 
Prevención
Para evitar los ataques de inyección SQL, se recomienda que la aplicación elimine de los valores de los parámetros proporcionados por el usuario órdenes SQL (como podrían ser “UNION” y “SELECT”) y caracteres específicos que se utilizan en la sintaxis del lenguaje SQL (“--”, “’”, “;”) antes de utilizar estos valores directamente en la consulta.
 
Inyección SQL Ciega
Este tipo de vulnerabilidades afectan al servidor. Este tipo de inyecciones de código son muy parecidas a las anteriores, su única diferencia es que la consulta SQL no devuelve ningún resultado visible al usuario, o cuando el aplicativo no nos permite concatenar consultas para extraer más información de la Base de Datos. En estos casos particulares sólo podemos inyectar consultas de tipo Booleanas (verdadero o falso) y comprobar los resultados devueltos por el aplicativo web para evaluar si el resultado de la consulta retorna “verdadero” o “falso” dependiendo si observamos algún cambio en el resultado devuelto.
 
Por ejemplo, si inyectamos en el parámetro “id” la sintaxis “and 1=1”, como 1 siempre es igual a 1 es una sintaxis que se evalúa como verdadera nos devolvera resultados.

Por otro lado, si se inyecta una condición falsa “and 1=2”, como la condición nunca se cumple la sintaxis SQL evalúa falso no devolvera nada.

El método anterior nos puede servir para comprobar si el aplicativo es vulnerable ante ataques de tipo “Inyección de SQL Ciega”. Sin embargo, para poder volcar información, de la BBDD, existe un método que consiste en modificar la consulta SQL que se realizaría a una consulta SQL Booleana. Las consultas serían de este tipo “¿El primer carácter de la contraseña del usuario administrador es una B?, ¿Es una C?”, etc.
 
Además, dado que tendríamos que realizar una consulta para cada carácter que queramos consultar por cada posición podríamos llegar a realizar hasta 300 consultas únicamente para averiguar el primer carácter de un único registro en la base de datos.
 
Para poder aumentar la velocidad en la extracción de datos se utiliza el concepto de divide y vencerás, para ello se utiliza el valor numérico ASCII de cada carácter.
 
De esta manera se pueden realizar consultas de tipo “¿El valor ASCII del primer carácter de la contraseña del usuario administrador es mayor que 100?”, “¿Es menor que 100?”, etc.

En la siguiente captura, se muestra la sintaxis de inyección para averiguar el primer carácter del usuario con el que se está accediendo a la Base de Datos.


En este caso, si comprobamos a qué carácter se corresponde el valor ASCII de 114, observaremos que el primer carácter del nombre de usuario con el que el aplicativo accede a la Base de Datos es “r”.

Herramienta sqlmap
sqlmap es una herramienta que es capaz de automatizar la extracción de información dada una vulnerabilidad de inyección SQL. Contiene distintos payloads para los motores de bases de datos más comunes. De esta manera, nos puede ayudar en la extracción específica de información ya que automáticamente ajusta la inyección SQL para realizar la consulta SQL necesaria para extraer la información requerida.
 
Es extremadamente útil en inyecciones de tipo SQL ciega en la que la extracción de datos se vuelve tan tediosa, sqlmap puede automatizar esta extracción.
 
Aunque también nos permite localizar vulnerabilidades de inyección se recomienda localizar la vulnerabilidad con las técnicas anteriormente descritas (o incluso mediante el scanner automático de Burp Suite) debido a la cantidad de datos que genera.
 
El funcionamiento general de sqlmap es invocarlo con el parámetro -u e indicarle la url (con el path completo) si la propia URL contiene los parámetros vulnerables ante una inyección SQL con el parámetro -p se indica el parámetro sobre el que se realizará la inyección.
 
El siguiente ejemplo, muestra el uso de sqlmap pasando una URL vulnerable que además dispone de un parámetro vulnerable id.
 
sqlmap -u "http://debiandev/sqlmap/mysql/get_int.php?id=1" -p id

Si por el contrario nuestra petición se envía a través del método POST, deberemos añadir el cuerpo de nuestra petición a través del parámetro --data, a continuación mostramos un ejemplo.
 
sqlmap -u "http://www.appvulnerable.com/login" --data"user=usuario,password=contraseña" -p "user"
 
Además, en caso de que la funcionalidad vulnerable se encuentre en la parte privada de la aplicación habrá que indicarle a sqlmap el identificador de sesión que nos autentica como usuario. En caso de que el identificador se encuentre en la cookie se le puede indicar a sqlmap con el valor --cookie.
 
sqlmap -u "http://www.appvulnerable.com/product" --data"category=Gifts" -p "category" --cookie"JSESSIONID=hkjgsdaf8s76fskghfsd8676ywerhg"
 
Además, sqlmap permite indicar toda una petición HTTP como parámetro de entrada. De esta manera, en caso que el aplicativo necesite algún dato más de la aplicación para poder procesar la respuesta (por ejemplo alguna cabecera) será mucho más fácil pasarle directamente una petición HTTP de ejemplo e indicarle el parámetro sobre el que realizar la inyección.
 
Por ejemplo, podemos guardar la siguiente petición HTTP "sqli.txt" y luego ejecutamos sqlmap pasándole la petición a través del parámetro -r e indicando el parámetro a probar
 
sqlmap -r sqli.txt -p "parámetro vulnerable"
 
Inyección de código y/o comandos
Este tipo de vulnerabilidades afectan al servidor. Las pruebas que se realizan tratan de determinar si es posible inyectar, a través de los parámetros de entrada proporcionados por el usuario, código que sea interpretado por el aplicativo (en caso que se encuentre desarrollado en un lenguaje interpretado como PHP, ASP, Python o Ruby) o comandos que sean ejecutados en el propio Sistema Operativo del Servidor.
 
Además, este tipo de vulnerabilidades son consideradas como críticas ya que es posible inyectar comandos directamente en el sistema. De esta manera, los comandos serán ejecutados con el mismo nivel de privilegios que tuviera el usuario con el que se inicia el servidor web. Por ejemplo si el servidor web se inicia con un usuario especialmente diseñado para ello (por ejemplo el usuario apache) este ataque puede tener limitaciones debido a que el usuario dispondrá de unos privilegios restringidos. Sin embargo, si el servidor web se inicia con el usuario root y existe una vulnerabilidad de inyección de código en el aplicativo el resultado puede ser devastador.
 
Para poder comprobar este tipo de técnicas se ha de comprobar si el aplicativo utiliza los datos de entrada, proporcionados por el usuario, directamente para la ejecución de un comando en el sistema. Si la entrada del usuario no es correctamente validada y no se filtran caracteres especiales, ni órdenes del sistema, un atacante podría introducir comandos que serían ejecutados por el servidor. 
 
Para realizar esta concatenación de comandos se pueden utilizar los caracteres especiales “;”, “&”, “&&”, “|” o “&&”.

Vulnerabilidades que impactan en el cliente
 
Cross Site Scripting Reflejado
Este tipo de vulnerabilidades afectan al cliente del aplicativo web. Se producen cuando un atacante consigue inyectar, en el aplicativo web, código que puede ser ejecutado directamente en el navegador web de los usuarios (por eso este tipo de vulnerabilidades afectan directamente a los clientes del aplicativo).
 
El problema radica de nuevo en la falta de validación de los valores enviados a través de los parámetros del aplicativo. Si no se eliminan ciertos caracteres especiales, propios de los lenguajes interpretados por el navegador (Por ejemplo, JavaScript), si los datos introducidos directamente por el usuario a través de los parámetros de entrada se reflejan directamente en el código HTML de la página web, el código JavaScript inyectado se incluirá en la página HTML como código legítimo de la misma y los navegadores de los usuarios ejecutarán este código.
 
Por otro lado, el código inyectado se ha de mostrar correctamente en el resultado de la respuesta HTML. En el caso que en la respuesta no se refleje todo el código inyectado (se eliminen ciertos caracteres especiales, o comandos JavaScript) el código inyectado no será funcional.

Como se puede deducir, se trata de un ataque de tipo no persistente, es decir, en ningún momento el código inyectado se guarda en el servidor. En su lugar, habría que generar la dirección URL con la inyección en el parámetro y utilizar técnicas de ingeniería social para enviar el enlace a los usuarios e intentar que accedan al mismo (se puedenutilizar acortadores de URL para intentar camuflar la URL).
 
La siguiente ilustración muestra cual es el flujo de explotación de este tipo de ataques “Cross Site Scripting reflejado”:


Por otro lado, es posible inyectar cualquier tipo de código JavaScript, el truco del mensaje de alerta (“<script>alert(‘hello’)</script>”) se suele utilizar para localizar y demostrar la vulnerabilidad. Un atacante podría inyectar código JavaScript para usurpar el identificador de sesión de los usuarios (siempre y cuando la cookie no se encuentre protegida mediante el atributo HttpOnly).

Cross Site Scripting Almacenado
De la misma manera que la vulnerabilidad “Cross Site Scripting Reflejado” es una vulnerabilidad que afecta al cliente del aplicativo web. La particularidad de la variante almacenada del Cross Site Scripting es que en este caso la inyección si se almacena en el Backend del aplicativo (En la Base de Datos) y la inyección se muestra a cualquier usuario que acceda a la página en la que se ha almacenado la inyección.
 
Este tipo de vulnerabilidades suele estar presente en portales que permiten la inserción de comentarios (en el caso que el aplicativo guarde en el comentario el código completo, cualquier usuario del foro que visite el comentario ejecutará de manera transparente el código inyectado por el atacante.). Por ejemplo, una tienda online que permita a los usuarios dejar comentarios de los productos, comentarios en aplicativos de Blogs y Foros, aplicativos colaborativos, etc.
 
La siguiente ilustración muestra el flujo de explotación de una vulnerabilidad de tipo “Cross Site Scripting almacenado”.
 

En todos estos casos, para que la aplicación sea vulnerable, el atacante ha de poder introducir código, que será interpretado por el navegador del usuario (JavaScript) y que se muestre correctamente en el resultado de la respuesta HTML. En el caso que en la respuesta no se refleje todo el código (se eliminen ciertos caracteres especiales o comandos JavaScript) el código inyectado no será funcional.

Análisis de los códigos de error
Algunos aplicativos no se encuentran debidamente configurados y se pueden producir ciertos mensajes de error ( Errores de la propia aplicación o en el servidor que lo sustenta), que son mostrados al usuario.
 
Dada la naturaleza de estos mensajes de error, es posible que se incluya información del error producido, la cual revele información sensible como el tipo de tecnologías utilizadas, el error exacto producido, campos, tablas u objetos que intervienen en el error, etc.
 
Toda esta información puede ser utilizada por un atacante para tratar de diseñar ataques más específicos contra la infraestructura o incluso revelar información sensible en las propias trazas de error.
  • Códigos de error
El propio estándar HTTP maneja unos códigos de error que se incluyen en la respuesta HTTP enviada por el servidor. Como pudimos comprobar en apartados anteriores, los códigos 400 corresponden a errores producidos en el cliente (por ejemplo un error 404 indica que el recurso solicitado no existe y un error 403 indica que el recurso solicitado existe pero no tenemos privilegios de acceso). Por otra parte, los errores HTTP 500 indican un error producido en el servidor.

  • Información en el cuerpo del mensaje
Información en el cuerpo del mensaje: Además del código de estado, el propio cuerpo del mensaje de error proporciona bastante información a cerca del error producido. La siguiente ilustración muestra un error en la base de datos en el que se puede apreciar la consulta que el servidor realiza contra la Base de Datos y genera el error.


Por otro lado, el siguiente error muestra el tipo y versión del servidor utilizado para sustentar la aplicación.


Vulnerabilidades en la lógica de negocio
Este tipo de vulnerabilidades aparecen cuando un atacante consigue modificar la operativa para la cual el aplicativo fue diseñado. Dependen ampliamente de la tipología del aplicativo y no existen unas técnicas específicas que se puedan utilizar dado que dependerá de cada caso concreto. A continuación se indican algunos ejemplos para que quede más claro:
  • Tienda Online en la que puedes adquirir productos y un atacante localiza una vulnerabilidad mediante la que no es necesario pagar por ellos (o pagar una cantidad inferior).
  • Aplicativo que dispone de códigos de fidelización con descuentos y un atacante puede generar los códigos desde la aplicación.
  • Aplicación Bancaria en la cual un atacante puede evitar que le cobren comisiones por realizar operaciones bancarias.
  • Aplicación Bancaria en la que un atacante puede realizar una transferencia con un importe negativo y el importe es abonado en su cuenta desde la cuenta del destinatario.
Port Swigger dispone de una academia gratuita en el que se explican las vulnerabilidades tipo web más comunes. Además, dispone de varios laboratorios con ejercicios de distintos niveles para practicar con algunas de ellas.
 
Podéis acceder a estos recursos a través del siguiente enlace (https://portswigger.net/web-security/all-materials)
 
En el siguiente enlace podéis obtener más información sobre la metodología de vulnerabilidades web (https://book.hacktricks.wiki/es/pentesting-web/web-vulnerabilities-methodology.html).