MITMProxy en las pruebas de QA

1. El problema de cómo testear “un autobús lleno”
2. El uso de MITMProxy como solución
3. DEMO

Una de las herramientas que usamos en nuestro departamento de QA en O2O es MITMproxy.

Un plan de prueba muy útil a la hora de testear las aplicaciones web y/o móviles que se desarrollan. En los procesos habituales que se realizan para el testeo de apps, siempre aparecen una serie de limitaciones con respecto a los datos de pruebas. Por esta razón, es muy útil aplicar este recurso, ya que, nos permitirá capturar y editar las peticiones que manda y recibe la aplicación, superando así, estas barreras.

El problema de cómo testear “un autobús lleno”


El trabajo del departamento de QA se puede resumir en asegurar la calidad del software que se está desarrollando y que se entrega al cliente final. Pero claro, el concepto de calidad es algo relativo por lo que se tienen que definir unos parámetros lo más objetivos posibles para así tener una visión lo más clara posible de la “calidad” del software. Ahí es donde entran en juego los planes de pruebas.

Según la definición del ISTQB (https://glossary.istqb.org/en/term/test-plan-3) un plan de pruebas es: “Un documento que describe el alcance, el enfoque, los recursos y la planificación de las actividades de prueba previstas”. Este documento permite recoger todas las actividades de testing que se llevan a cabo ya sea por niveles de pruebas (pruebas unitarias, de componentes, de integración, …)  o por tipos de pruebas (de usabilidad, accesibilidad, rendimiento, seguridad, regresión…) y sirve como registro de todo el proceso de testing.

Para preparar cualquier tipo de plan de pruebas, aparte de disponer de un documento funcional donde están definidos los requisitos también hace falta disponer de una batería de datos de pruebas lo más extensa posible para así cubrir el máximo de casos. Pero ahí nos encontramos con el problema de que en función de cómo estemos generando esos datos de pruebas nos podemos encontrar con la limitación de que no podemos disponer de todos los datos que necesitamos.

Vamos a utilizar un ejemplo con una aplicación de venta de billetes de autobuses para ver de forma clara a lo que nos referimos con la limitación con la que nos encontramos con los datos de pruebas. Está claro que el principal objetivo de una aplicación de venta de billetes es el de permitir al usuario la compra de billetes por lo que en el plan de pruebas hay que tener en cuenta las casuísticas que permiten al usuario comprar el billete (clases de equivalencia válidas) como las que no (clases de equivalencia no válidas)

Dentro de las clases de equivalencia no válidas, un típico caso de prueba sería comprobar cómo se comporta la aplicación cuando el autobús ya está completo y ya no quedan billetes disponibles. Sin entrar mucho en detalle el resultado esperado de dicho caso de prueba sería el de que el usuario no pueda completar la compra de un billete cuando el autobús está completo. Pero el problema es cómo conseguir la situación inicial de tener “un autobús completo”.

Ante ese problema, la primera intuición sería la de manualmente desde la propia app buscar un trayecto para el que el autobús estuviera ya completo pero rápidamente se ve como esta solución no es la mejor. Primero en cuestión de tiempo: si lo hacemos manualmente como lo haría un usuario de la app en función de la “suerte” que tuviésemos la búsqueda de ese “autobús completo” nos llevaría más o menos tiempo. Pero aún si asumimos ese coste en tiempo para la prueba ese coste lo tendríamos a cada vez que se ejecutara el caso de prueba ya que una ruta que “hoy” tiene el autobús completo puede que “mañana” ya no lo esté.

Otra solución a lo de encontrar un “autobús completo” sería la de nosotros mismos seleccionar una ruta cualquiera y comprar tantos billetes sean necesarios para de esta forma llenar el autobús. De esta forma conseguimos nuestra condición inicial para el caso de prueba, pero de nuevo nos encontramos ante una solución nada eficiente. Al final vamos a dedicar más tiempo en preparar el caso de prueba que en su ejecución…

De forma general ante estos problemas con la obtención de los datos de pruebas se suele pedir ayuda al equipo de backend para acceder a las bases de datos y así modificar directamente los valores necesarios del tal forma, que obtengamos las casuísticas de pruebas que se necesitan. Volviendo a nuestro ejemplo de encontrar un “autobús completo” teniendo acceso a la base de datos sería simplemente modificar el valor de plazas vacías a 0 para una ruta concreta (suponiendo que dicho parámetro esté en la base de datos) y de esta forma en la app al buscar esa ruta modificada siempre vamos a obtener que el autobús está completo.

El modificar los valores en la base de datos es la mejor solución para poder simular esas condiciones de pruebas difíciles de obtener. Todo ello implica modificar la base de datos, que no siempre es posible, motivado por seguridad, entornos o arquitectura.

Sin tener que bajar al nivel de las bases de datos, las aplicaciones hacen uso de endpoints para comunicarse con el backend (que a su vez es quien se comunica con las bases de datos) por lo que si conseguimos interceptar esas llamadas que se realizan entre la app y el backend y además las podemos modificar, vamos a conseguir el mismo resultado que si modificamos las bases de datos. Justo eso es lo que nos permite conseguir la herramienta MITM Proxy.

El uso de MITMProxy como solución

Qué es MITMProxy

MITM proxy (https://mitmproxy.org/) es una herramienta open source que nos permite levantar un servidor proxy tipo” Man in the Middle”. El concepto de “Man in the Middle” viene de un tipo de ataque que se usa en criptografía en que el atacante se sitúa en el medio de la comunicación entre dos puntos enlazados. Lo más habitual es realizar este tipo de ataques entre un cliente y un servidor. De esta forma el atacante al situarse en el medio de la comunicación va a simular ser el servidor desde el punto de vista del cliente e inversamente simular ser el cliente desde el punto de vista del servidor. MIT proxy nos permite obtener justo eso por lo que es una herramienta con la que vamos a poder interceptar, inspeccionar y modificar las llamadas que realiza cualquier tipo de cliente pero nos vamos a centrar en su uso y configuración en aplicaciones móviles.

Tras instalar MITMproxy en nuestra máquina en verdad estamos instalando tres productos: una herramienta de línea de comandos (mitmproxy), una interfaz web (mitmweb) y el acceso a un API python (para poder implementar scripts). En este post nos vamos a centrar mitmweb que una la interfaz web y es la forma más sencilla para familiarizarse con la herramienta.

Para lanzar la interfaz web mitmweb basta con usar el comando `mitmweb` en la terminal y de forma automática nos va a levantar la siguiente web en nuestro navegador.

Como se puede observar se levanta una interfaz que tiene sus similitudes con la consola de devTools del navegador Chrome. Desde esta interfaz web vamos a poder buscar, interceptar e inspeccionar las llamadas que va a recibir el servidor proxy pero para poder ver esas llamadas lo primero que tenemos que hacer es conectarnos desde los móviles al servidor que se ha levantado.

 

Configuración de MITMProxy en los móviles

Cuando se lanza el comando mitmweb se puede ver que en la terminal se indica como output dos direcciones:

  • Web server listening at http://127.0.0.1:8081/ ⇒ que corresponde a la dirección que se abre con la consola web donde vamos a poder controlar el proxy
  • Proxy server listening at http://*:8080 ⇒ que corresponde a la dirección en la que se ha levantado el servidor proxy

Es esta última dirección la que vamos a tener que apuntar nuestros dispositivos móviles para que de esta forma las llamadas que se realicen apunten al servidor proxy y así poder verlas en el servidor web.

Como se puede ver en nuestro caso nos indica que el servidor proxy está levantado en la dirección http://*:8080. El asterisco en realidad corresponde a la ip del ordenador en el que hemos lanzado el comando mitmweb (en nuestro caso 10.3.5.202) el resto de la dirección corresponde al puerto (en nuestro caso el 8080). Vamos a utilizar esos datos de ip y puerto para configurar el proxy en los dispositivos móviles.

Dispositivos Android (en función de cada dispositivo variará, pero de forma general):

  • Acceder a la configuración de Wi-Fi
  • Pulsar para editar los detalles de la red
  • Seleccionar la opción de proxy manual
  • Introducir la ip donde está lanzado mitmweb (10.3.5.202) como nombre del host
  • Introducir el número puerto que nos devuelve mitmweb (8080)
  • Pulsar en guardar

Dispositivos iOS:

  • Acceder a Ajustes
  • Acceder a la sección de Wi-Fi
  • Pulsar en el botón (i) de la Wi-Fi a la que se está conectado
  • Pulsar en la opción ‘configurar proxy’
  • Seleccionar la opción de ‘Manual’
  • Introducir la ip donde está lanzado mitmweb (10.3.5.202) como servidor
  • Introducir el número puerto el que nos devuelve mitmweb (8080)
  • Pulsar en guardar

Una vez tengamos conectado el móvil al proxy ya vamos a poder ver en la interfaz web de mimtproxy las llamadas que se realizan como se puede ver en el siguiente video de demo:

Por defecto solo vamos a poder ver las llamadas que utilicen el protocolo http pero las llamadas que utilicen https van a fallar porque falta por instalar el certificado (que genera el propio mitmpoxy) en los dispositivos. Para ello desde el navegador del dispositivo conectado al proxy accedemos a la web http:/mitm.it y veremos la siguiente página:

En esta página web (que genera el propio mitmproxy) vamos a poder descargar el certificado de autoridad de mitmproxy simplemente pulsando un botón correspondiente a la plataforma en la que estemos. Una vez instalado el certificado en el dispositivo ya vamos a poder ver la llamadas https

En el caso de iOS una vez instalado el certificado hay que hacer los siguientes pasos adicionales para activarlo:

  • Ir a Ajustes>General>Información>Ajustes de certif. de confianza
  • Activar el check del certificado mitmproxy

Una vez ya tengamos realizados estos pasos ya el dispositivo está totalmente configurado por lo que al lanzar una aplicación (que tenga el pinning desactivado) vamos a poder ver las llamadas que se envían y reciben:

 

Como interceptar y editar las llamadas en MITMProxy

Pero volviendo a nuestro problema de cómo testear “un autobús lleno” la verdadera utilidad de mitmproxy es la de poder interceptar y editar la respuesta de las llamadas y lo podemos conseguir de la siguiente manera:

  • En el campo ‘intercept’ introducimos la llamada que queremos interceptar. Con esto vamos a parar la llamada en dos puntos:
    • (1) Cuando el proxy recibe la request desde el dispositivo
    • (2) Cuando el proxy recibe la response desde el servidor.
  • Cuando al proxy llega la llamada a interceptar esta se marca de color naranja y al pulsar sobre ella se nos muestra el contenido de la request que ha llegado al proxy

  • Al pulsar en el icono «lápiz» todos los campos de la petición (endpoint, cabeceras, payload, …) se cambian a campos editables para que se puedan hacer los cambios que se quieran a la petición antes de que esta llegue al servidor

Una vez hechos los cambios pulsando en el botón «Resume»(o tecla ‘a’) hacemos que la petición (modificada o no) siga su camino hasta el servidor y entonces llegamos al punto (2) en el que el proxy recibe la respuesta y la para antes de que llegue a la app.

  • En este punto nos aparece la pestaña ‘Response’ en la que vamos a poder ver todo el contenido de la respuesta (código de respuesta, cabeceras, contenido de la respuesta, ….) y de nuevo pulsando en el icono de editar vamos a poder modificar todos esos campos para así poder editar la respuesta que finalmente le va a llegar a la app.

Finalmente pulsando de nuevo en el botón «Resume»(o tecla ‘a’) hacemos que la respuesta (modificada o no) finalice su camino y llegue a la app.

DEMO

Siguiendo los pasos anteriores, en el siguiente video vemos cómo podemos hacer que un trayecto que en realidad tiene plazas libres pase a estar completo editando la respuesta que recibe la aplicación y así conseguir nuestro objetivo de simular la casuística de un “autobús lleno”.

Anterior

Google I/O 2022

Siguiente

Cuándo usar microservicios

Talento O2O

¿Te apetece formar parte de nuestro equipo?

Mira las oportunidades