RCE de FreeSWITCH por SIP MESSAGE, explotada en entornos reales (CVE-2026-116779)
Un SIP MESSAGE a un perfil estándar de FreeSWITCH puede ejecutar comandos API y del sistema; corregido en 1.11.3 y explotado en entornos reales.
Resumen
- Un SIP MESSAGE manipulado hacia un perfil de FreeSWITCH puede seleccionar el protocolo de chat
apiy ejecutar comandos de la API, incluidos comandos del sistema, como el proceso de FreeSWITCH. SignalWire publicó CVE-2026-116779 el 5 de noviembre de 2026. - Todas las versiones hasta 1.11.2 se ven afectadas. Los perfiles internos y externos estándar aceptan MESSAGE entrantes por defecto, y un usuario de directorio
defaultestándar sin contraseña puede hacer que el ataque no requiera autenticación. - El aviso la puntúa CVSS v3.1 9.8 Critical e indica que se ha observado explotación de esta ruta en entornos reales. La CVE no está en el catálogo KEV de CISA al 6 de noviembre de 2026.
- Actualice a FreeSWITCH 1.11.3 o posterior. Si no puede, configure
enable-chat=falseen los perfiles que no necesiten chat SIP; consulte «¿Cómo lo corrijo?».
¿Estoy afectado?
Está expuesto solo cuando se cumplen todas estas condiciones:
- El host ejecuta FreeSWITCH 1.11.2 o anterior.
- Al menos un perfil SIP acepta MESSAGE entrantes. El manejo de chat está activo salvo que el perfil configure
enable-chat=false, y los perfiles internos y externos estándar deconf/vanillalo dejan activo. - El atacante puede alcanzar ese perfil por SIP, o puede entregar un MESSAGE a través de un trunk o un par que sí puede.
- El perfil no rechaza ya el protocolo de chat
api. Las versiones anteriores a 1.11.3 no tienen el ajusteenable-chat-api-proto, así que la ruta está disponible en todos los perfiles que aceptan MESSAGE.
La autenticación de MESSAGE cambia quién puede alcanzar la ruta, pero no la elimina. Desde FreeSWITCH 1.10.7, auth-messages está activo por defecto, así que basta cualquier cuenta del perfil: una extensión, un teléfono o un par de trunk que pueda registrarse. El archivo estándar conf/vanilla/directory/default/default.xml define un usuario default sin password ni a1-hash; un usuario de directorio sin ninguno de los dos se autentica salvo que allow-empty-password sea false para él. Eso hace que la configuración estándar no requiera autenticación.
La ACL entrante no cubre MESSAGE, así que endurecer la ACL no saca un perfil del alcance. Un perfil con enable-chat=false no llega al controlador vulnerable.
| Rama | Versiones afectadas | Versión corregida |
|---|---|---|
| FreeSWITCH 1.11 | 1.11.0 a 1.11.2 | 1.11.3 (publicada el 28 de agosto de 2026) |
| FreeSWITCH 1.10 y anteriores | todas las versiones anteriores a 1.11.3 | 1.11.3 |
Compruebe qué ejecuta el host y qué perfiles aceptan chat:
# FreeSWITCH version
fs_cli -x "version"
# If fs_cli is unavailable, run the binary directly
freeswitch -version
# Profiles and whether inbound chat is disabled
grep -R "enable-chat" /etc/freeswitch/sip_profiles/ 2>/dev/null
# Directory users with no password or a1-hash
grep -R -E "<user id=|<param name=\"(password|a1-hash)\"" /etc/freeswitch/directory/ 2>/dev/null
Un perfil sin la línea enable-chat=false está en el alcance. El usuario default es el primero que debe buscar: si no tiene password ni a1-hash, un MESSAGE puede alcanzar la ruta sin cuenta.
¿Cómo lo corrijo?
- Actualice a FreeSWITCH 1.11.3 o posterior. Use el repositorio de paquetes de SignalWire o reconstruya desde la etiqueta v1.11.3 y reinicie FreeSWITCH. Las notas de la versión enumeran el nuevo parámetro
enable-chat-api-protoy el límite en la división del usuario To. - Si construye sus propios paquetes, reconstruya cada nodo que ejecute
mod_sofiaymod_dptools; la corrección está en ambos módulos y en los perfiles vanilla de ejemplo. - Si no puede actualizar, desactive el chat entrante en cada perfil que no lo necesite:
<param name="enable-chat" value="false"/>Añada la línea a cada perfil en/etc/freeswitch/sip_profiles/y recargue el perfil o reinicie FreeSWITCH. Esto cierra la ruta porque el controlador regresa antes de analizar el selector de protocolo. El coste es que el perfil deja de entregar todo el chat SIP MESSAGE entrante, no solo el protocoloapi. - Si necesita chat y no puede actualizar, elimine todos los usuarios de directorio sin
passwordnia1-hash, y configureallow-empty-passworden false para los demás. Combinado conauth-messages, esto reduce el ataque a un usuario autenticado; no cierra la ruta, porque cualquier cuenta puede seguir seleccionandoapi. disable_system_api_commands=trueelimina la APIsystempero no la ruta. El atacante aún puede alcanzar todas las demás API registradas, incluida la carga de módulos y el origen de llamadas. Trátelo como una medida de reducción, no como una corrección.
¿Cuál es la causa raíz?
El controlador de SIP MESSAGE trata la parte izquierda del usuario To como un nombre de protocolo de chat y la parte derecha como la dirección, y el protocolo de chat api ejecuta su dirección como un comando de la API de FreeSWITCH. En src/mod/endpoints/mod_sofia/sofia_presence.c, sofia_presence_handle_sip_i_message() hace esto:
if ((p = strchr(to_user, '+')) && p != to_user) {
switch_copy_string(proto, to_user, sizeof(proto));
p = strchr(proto, '+');
*p++ = '\0';
if ((to_addr = strdup(p))) {
if ((p = strchr(to_addr, '+'))) {
*p = '@';
}
}
} else {
to_addr = switch_mprintf("%s@%s", to_user, to_host);
}
Después coloca proto en la cabecera to_proto y to_addr en la cabecera to de un SWITCH_EVENT_MESSAGE. Nada limita el nombre de protocolo que el remitente puede elegir. mod_dptools registra la interfaz de chat api junto a la de event:
SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
api_chat_send() toma la cabecera to, la decodifica como URL, la divide en el primer espacio y pasa las dos partes a switch_api_execute():
if (to) {
char *v = NULL;
switch_stream_handle_t stream = { 0 };
char *cmd = NULL, *arg;
if (!(v = switch_core_get_variable_dup(to))) {
v = strdup(to);
}
cmd = v;
switch_assert(cmd);
switch_url_decode(cmd);
if ((arg = strchr(cmd, ' '))) {
*arg++ = '\0';
}
SWITCH_STANDARD_STREAM(stream);
switch_api_execute(cmd, arg, NULL, &stream);
Un MESSAGE a sip:api+system%20id@example.com configura proto como api y to_addr como system%20id. api_chat_send() decodifica la dirección a system id, la divide en el comando system y el argumento id, y lo ejecuta. La salida se devuelve como respuesta de chat.
¿Cómo se explota?
- El atacante envía un SIP MESSAGE a un perfil que acepta chat entrante, dirigido a
sip:api+system%20id@targeto a otro comando de la API codificado de la misma forma. - Si el perfil exige autenticación de MESSAGE, el atacante usa cualquier cuenta del perfil, o el usuario
defaultestándar que no tiene contraseña nia1-hash. sofia_presence_handle_sip_i_message()divide el usuario To en el primer+: la parte izquierda pasa ato_proto=api, la derecha ato=system%20id.- La capa de chat distribuye el mensaje a la interfaz
apiregistrada pormod_dptools. api_chat_send()decodificasystem%20id, lo divide ensystemeid, y llama aswitch_api_execute("system", "id").- El comando se ejecuta con los privilegios del proceso de FreeSWITCH. El atacante puede ejecutar otros comandos
system, cargar módulos, originar llamadas o leer la configuración y las credenciales; cuandomod_luaestá cargado, el Lua en línea con la biblioteca estándar completa es un segundo punto de ejecución.
El aviso indica que se ha observado explotación de esta ruta en entornos reales. No da fecha, número de víctimas, secuencia de comandos ni indicadores, y no se enumera ningún código de prueba de concepto público.
¿Cómo se desarrolla el ataque?
Un SIP MESSAGE cuyo usuario To empieza por api+ selecciona el protocolo de chat de ejecución de comandos, y la dirección después del signo más se ejecuta como un comando de la API de FreeSWITCH.
¿Qué puede hacer un atacante?
Un atacante que puede entregar un MESSAGE aceptado a un perfil afectado puede ejecutar comandos de la API de FreeSWITCH con los privilegios del proceso de FreeSWITCH. Eso incluye:
- Comandos del sistema mediante la API
system, que los ejecuta como el usuario de FreeSWITCH. - Divulgación de la configuración y las credenciales, incluidas las credenciales de cuentas SIP y trunks que el proceso puede leer.
- Control total de las llamadas: originar, puentear, escuchar y cortar llamadas.
- Carga de módulos y otras API registradas, que pueden ampliar el alcance del atacante más allá del comando
system. - Ejecución de Lua en línea cuando
mod_luaestá cargado, como en la configuración estándar, con la biblioteca estándar completa de Lua.
Las condiciones se enumeran completas: un perfil SIP accesible que acepta MESSAGE, enable-chat que no sea false, y o bien la autenticación de MESSAGE satisfecha por cualquier cuenta, o bien un usuario de directorio estándar sin contraseña ni a1-hash. El proceso suele ejecutarse como un usuario freeswitch sin privilegios; el aviso no afirma root. El impacto sigue siendo el control total del servicio de telefonía y de los datos que puede leer.
¿Por qué funciona la corrección?
La corrección añade un indicador por perfil, desactivado por defecto, y rechaza el protocolo api antes de distribuir el mensaje:
+ if (!strcasecmp(proto, "api") && !sofia_test_pflag(profile, PFLAG_ENABLE_CHAT_API_PROTO)) {
+ /* p is the rest of the To user, still percent-encoded and bounded by the proto buffer. */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "Profile [%s] rejected a MESSAGE from %s@%s (%s:%d) addressed to the 'api' chat proto [%s]. "
+ "Set enable-chat-api-proto=true on the profile to permit it.\n",
+ profile->name, switch_str_nil(from_user), switch_str_nil(from_host), network_ip, network_port, p);
+
+ nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
+
+ if (full_from) {
+ su_free(nua_handle_get_home(nh), full_from);
+ }
+
+ return;
+ }
La comparación no distingue mayúsculas de minúsculas para coincidir con el registro de chat, que se crea sin distinguirlas. Un MESSAGE que selecciona api en un perfil sin el indicador recibe un 403 y se registra con el origen y el comando solicitado. Los mensajes sin selector de protocolo, o con otro protocolo de chat, se enrutan sin cambios. El indicador se entrega comentado en los cuatro perfiles vanilla y en el ejemplo de mod_sofia, así que el valor predeterminado es cerrado. La corrección es completa para esta ruta; no elimina la interfaz de chat api, pero la sitúa detrás de una activación explícita.
¿Cómo compruebo si estuve comprometido?
No hay indicadores de compromiso publicados. Las comprobaciones siguientes encuentran el patrón de la solicitud y la configuración que hacía accesible la ruta, no un compromiso confirmado:
# MESSAGE requests whose To user selects the api protocol
sudo grep -iE "MESSAGE.*api\+" /var/log/freeswitch/freeswitch.log
# On 1.11.3 and later, rejected attempts are logged with this text
sudo grep -i "addressed to the 'api' chat proto" /var/log/freeswitch/freeswitch.log
# Whether mod_lua is loaded, which adds the inline-Lua sink
fs_cli -x "module_exists mod_lua"
Antes de 1.11.3, una solicitud correcta puede no dejar ninguna advertencia, y el registro puede anotar solo un MESSAGE normal. Busque llamadas salientes inesperadas, archivos nuevos en el spool o los directorios de scripts de FreeSWITCH, dialplans modificados, nuevos registros SIP y cualquier salida de comando que el atacante pudiera haber recibido. Si no puede descartar una solicitud correcta, trate el host como comprometido, reconstrúyalo, renueve las credenciales SIP y de trunk, y revise los registros de llamadas.
Cronología
- 2026-08-26: la corrección se confirma en la PR #3135, que añade
enable-chat-api-protoy la respuesta 403. - 2026-08-28: se publica FreeSWITCH 1.11.3 con la corrección.
- 2026-10-28: se publica el aviso de seguridad de GitHub e indica que se ha observado explotación de esta ruta en entornos reales.
- 2026-11-05: se publica CVE-2026-116779 con CVSS v3.1 9.8.
- 2026-11-06: la CVE no está en el catálogo KEV de CISA; no hay indicadores ni detalles de víctimas públicos.
Preguntas frecuentes
¿Mi FreeSWITCH está expuesto si solo uso trunks SIP?
Sí, si un trunk puede entregar un MESSAGE a un perfil que acepta chat. Basta una cuenta de trunk autenticada, y el usuario default estándar puede eliminar por completo el paso de autenticación. Configure enable-chat=false en los perfiles que no necesiten chat, o actualice.
¿Afecta esto a los proveedores de PBX alojados y centros de contacto?
Cualquier proveedor que ejecute FreeSWITCH 1.11.2 o anterior con chat entrante activo está expuesto. La corrección está en el motor, así que el proveedor debe actualizar o desactivar el chat en los perfiles que expone. Pregunte a su proveedor qué versión ejecuta.
¿El ataque no requiere autenticación?
En la configuración estándar conf/vanilla, sí, porque el usuario de directorio default no tiene contraseña ni a1-hash. Si ese usuario se elimina y allow-empty-password es false, el atacante necesita una cuenta en el perfil, como una extensión o un par de trunk. Sigue siendo un listón bajo.
¿Se explotó en entornos reales?
El aviso indica que se ha observado explotación de esta ruta. No da fecha, número de víctimas ni indicadores. La CVE no está en el catálogo KEV de CISA al 6 de noviembre de 2026.
¿disable_system_api_commands=true corrige la falla?
No. Elimina la API system, pero la ruta sigue alcanzando todas las demás API registradas, incluida la carga de módulos y el origen de llamadas. Úselo solo como medida adicional de reducción, no como sustituto de la actualización.
¿La corrección rompe el chat SIP normal?
No. Solo bloquea el protocolo api salvo que el perfil configure enable-chat-api-proto=true. Los mensajes sin selector de protocolo, o con otro protocolo de chat, se enrutan como antes.
Encuentre servicios SIP expuestos con Ostorlab
El descubrimiento de superficie de ataque de Ostorlab inventaría sus hosts expuestos a Internet y los servicios que exponen. Úselo para listar los sistemas que responden en los puertos SIP y compruebe primero su versión de FreeSWITCH y la configuración de los perfiles.
Referencias
- Aviso de seguridad de FreeSWITCH GHSA-mg63-h38w-8p9p, publicado el 28 de octubre de 2026, la causa raíz, las configuraciones afectadas, las soluciones provisionales y la declaración de explotación: https://github.com/signalwire/freeswitch/security/advisories/GHSA-mg63-h38w-8p9p (comprobado el 6 de noviembre de 2026)
- Registro CVE-2026-116779, publicado el 5 de noviembre de 2026, CVSS v3.1 9.8 y el rango afectado: https://www.cve.org/CVERecord?id=CVE-2026-116779 (comprobado el 6 de noviembre de 2026)
- Commit de FreeSWITCH 7015f6a73ab3d67fed5fbfc277ecfb88a74c2a86, «Add enable-chat-api-proto to gate the api chat proto», 26 de agosto de 2026: https://github.com/signalwire/freeswitch/commit/7015f6a73ab3d67fed5fbfc277ecfb88a74c2a86 (comprobado el 6 de noviembre de 2026)
- Pull request de FreeSWITCH #3135, la corrección y los cambios de los perfiles vanilla: https://github.com/signalwire/freeswitch/pull/3135 (comprobado el 6 de noviembre de 2026)
- Notas de la versión v1.11.3 de FreeSWITCH, 28 de agosto de 2026, el nuevo parámetro y el límite del usuario To: https://github.com/signalwire/freeswitch/releases/tag/v1.11.3 (comprobado el 6 de noviembre de 2026)
- Archivo
sofia_presence.cde FreeSWITCH en v1.11.2, la división vulnerable del usuario To: https://github.com/signalwire/freeswitch/blob/v1.11.2/src/mod/endpoints/mod_sofia/sofia_presence.c (comprobado el 6 de noviembre de 2026) - Archivo
mod_dptools.cde FreeSWITCH en v1.11.2, la interfaz de chatapiyapi_chat_send(): https://github.com/signalwire/freeswitch/blob/v1.11.2/src/mod/applications/mod_dptools/mod_dptools.c (comprobado el 6 de noviembre de 2026) - Página del proyecto FreeSWITCH, la declaración de que impulsa operadores y centros de contacto: https://freeswitch.com/ (comprobado el 6 de noviembre de 2026)
- Docker Hub,
safarov/freeswitch, 1,366,696 descargas, una cifra de alcance comunitario: https://hub.docker.com/r/safarov/freeswitch (comprobado el 6 de noviembre de 2026) - GitHub,
signalwire/freeswitch, 5,283 estrellas, una cifra de alcance del repositorio: https://github.com/signalwire/freeswitch (comprobado el 6 de noviembre de 2026) - Flujo JSON del catálogo Known Exploited Vulnerabilities de CISA, comprobado para CVE-2026-116779 el 6 de noviembre de 2026 (no incluida): https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (comprobado el 6 de noviembre de 2026)