RCE FreeSWITCH via SIP MESSAGE, exploitée dans la nature (CVE-2026-116779)
Un SIP MESSAGE vers un profil FreeSWITCH standard peut exécuter des commandes API et système ; corrigé en 1.11.3 et exploité dans la nature.
En bref
- Un SIP MESSAGE forgé vers un profil FreeSWITCH peut sélectionner le protocole de chat
apiet exécuter des commandes API FreeSWITCH, y compris des commandes système, avec le processus FreeSWITCH. SignalWire a publié CVE-2026-116779 le 5 novembre 2026. - Toutes les versions jusqu'à 1.11.2 sont concernées. Les profils internes et externes standards acceptent les MESSAGE entrants par défaut, et un utilisateur d'annuaire
defaultstandard sans mot de passe peut rendre l'attaque non authentifiée. - L'avis la note CVSS v3.1 9,8 Critical et indique que l'exploitation de ce chemin a été observée dans la nature. La CVE n'est pas au catalogue KEV de la CISA au 6 novembre 2026.
- Mettez à niveau vers FreeSWITCH 1.11.3 ou ultérieur. Si vous ne pouvez pas, réglez
enable-chat=falsesur les profils qui n'ont pas besoin du chat SIP ; voir « Comment corriger ? ».
Suis-je concerné ?
Vous êtes exposé uniquement lorsque toutes ces conditions sont réunies :
- L'hôte exécute FreeSWITCH 1.11.2 ou antérieur.
- Au moins un profil SIP accepte les MESSAGE entrants. Le traitement du chat est actif sauf si le profil règle
enable-chat=false, et les profils internes et externes standards deconf/vanillale laissent actif. - L'attaquant peut atteindre ce profil en SIP, ou peut livrer un MESSAGE via un trunk ou un pair qui le peut.
- Le profil ne rejette pas déjà le protocole de chat
api. Les versions antérieures à 1.11.3 n'ont pas de réglageenable-chat-api-proto, donc la route est disponible sur chaque profil qui accepte les MESSAGE.
L'authentification des MESSAGE change qui peut atteindre la route, mais ne la supprime pas. Depuis FreeSWITCH 1.10.7, auth-messages est actif par défaut, donc un compte du profil suffit : une extension, un téléphone ou un pair de trunk qui peut s'enregistrer. Le fichier standard conf/vanilla/directory/default/default.xml définit un utilisateur default sans password et sans a1-hash ; un utilisateur d'annuaire sans l'un ni l'autre s'authentifie sauf si allow-empty-password vaut false pour lui. La configuration standard est donc non authentifiée.
L'ACL entrante ne couvre pas les MESSAGE, donc resserrer l'ACL ne sort pas un profil du périmètre. Un profil avec enable-chat=false n'atteint pas le gestionnaire vulnérable.
| Branche | Versions concernées | Version corrigée |
|---|---|---|
| FreeSWITCH 1.11 | 1.11.0 à 1.11.2 | 1.11.3 (publiée le 28 août 2026) |
| FreeSWITCH 1.10 et antérieures | toutes les versions avant 1.11.3 | 1.11.3 |
Vérifiez ce que l'hôte exécute et quels profils acceptent le 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 profil sans ligne enable-chat=false est dans le périmètre. L'utilisateur default est le premier à chercher : s'il n'a ni password ni a1-hash, un MESSAGE peut atteindre la route sans compte.
Comment corriger ?
- Mettez à niveau vers FreeSWITCH 1.11.3 ou ultérieur. Utilisez le dépôt de paquets SignalWire ou reconstruisez depuis l'étiquette v1.11.3, puis redémarrez FreeSWITCH. Les notes de version listent le nouveau paramètre
enable-chat-api-protoet la limite sur la découpe de l'utilisateur To. - Si vous construisez vos propres paquets, reconstruisez chaque nœud qui exécute
mod_sofiaetmod_dptools; le correctif est dans les deux modules et dans les exemples de profils vanilla. - Si vous ne pouvez pas mettre à niveau, désactivez le chat entrant sur chaque profil qui n'en a pas besoin :
<param name="enable-chat" value="false"/>Ajoutez la ligne à chaque profil dans/etc/freeswitch/sip_profiles/, puis rechargez le profil ou redémarrez FreeSWITCH. Cela ferme la route car le gestionnaire revient avant d'analyser le sélecteur de protocole. Le coût est que le profil cesse de livrer tout le chat SIP MESSAGE entrant, pas seulement le protocoleapi. - Si vous avez besoin du chat et ne pouvez pas mettre à niveau, supprimez chaque utilisateur d'annuaire sans
passwordnia1-hash, et réglezallow-empty-passwordsur false pour les autres. Combiné àauth-messages, cela réduit l'attaque à un utilisateur authentifié ; cela ne ferme pas la route, car tout compte peut encore sélectionnerapi. disable_system_api_commands=truesupprime l'APIsystemmais pas la route. L'attaquant peut encore atteindre toutes les autres API enregistrées, y compris le chargement de modules et l'origination d'appels. Traitez-le comme une mesure de réduction, pas comme un correctif.
Quelle est la cause racine ?
Le gestionnaire de SIP MESSAGE traite la partie gauche de l'utilisateur To comme un nom de protocole de chat et la partie droite comme l'adresse, et le protocole de chat api exécute son adresse comme une commande API FreeSWITCH. Dans src/mod/endpoints/mod_sofia/sofia_presence.c, sofia_presence_handle_sip_i_message() fait ceci :
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);
}
Il place ensuite proto dans l'en-tête to_proto et to_addr dans l'en-tête to d'un SWITCH_EVENT_MESSAGE. Rien ne limite le nom de protocole que l'expéditeur peut choisir. mod_dptools enregistre l'interface de chat api à côté de event :
SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
api_chat_send() prend l'en-tête to, le décode en URL, le coupe au premier espace et passe les deux parties à 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 vers sip:api+system%20id@example.com règle proto sur api et to_addr sur system%20id. api_chat_send() décode l'adresse en system id, la coupe en commande system et argument id, et l'exécute. La sortie est renvoyée comme réponse de chat.
Comment la faille est-elle exploitée ?
- L'attaquant envoie un SIP MESSAGE à un profil qui accepte le chat entrant, adressé à
sip:api+system%20id@targetou à une autre commande API encodée de la même façon. - Si le profil impose l'authentification des MESSAGE, l'attaquant utilise un compte du profil, ou l'utilisateur
defaultstandard qui n'a ni mot de passe nia1-hash. sofia_presence_handle_sip_i_message()coupe l'utilisateur To au premier+: la partie gauche devientto_proto=api, la partie droite devientto=system%20id.- La couche de chat distribue le message à l'interface
apienregistrée parmod_dptools. api_chat_send()décodesystem%20id, le coupe ensystemetid, et appelleswitch_api_execute("system", "id").- La commande s'exécute avec les privilèges du processus FreeSWITCH. L'attaquant peut lancer d'autres commandes
system, charger des modules, originer des appels ou lire la configuration et les identifiants ; lorsquemod_luaest chargé, le Lua en ligne avec la bibliothèque standard complète est un second point d'exécution.
L'avis indique que l'exploitation de ce chemin a été observée dans la nature. Il ne donne ni date, ni nombre de victimes, ni séquence de commandes, ni indicateurs, et aucun code de preuve de concept public n'est listé.
Comment se déroule l'attaque ?
Un SIP MESSAGE dont l'utilisateur To commence par api+ sélectionne le protocole de chat d'exécution de commandes, et l'adresse après le plus est exécutée comme commande API FreeSWITCH.
Que peut faire un attaquant ?
Un attaquant qui peut livrer un MESSAGE accepté à un profil concerné peut exécuter des commandes API FreeSWITCH avec les privilèges du processus FreeSWITCH. Cela inclut :
- Des commandes système via l'API
system, qui les exécute en tant qu'utilisateur FreeSWITCH. - La divulgation de la configuration et des identifiants, y compris les identifiants de comptes SIP et de trunks que le processus peut lire.
- Le contrôle total des appels : origination, pontage, écoute et coupure des appels.
- Le chargement de modules et d'autres API enregistrées, qui peuvent étendre la portée de l'attaquant au-delà de la commande
system. - L'exécution de Lua en ligne lorsque
mod_luaest chargé, comme dans la configuration standard, avec la bibliothèque standard Lua complète.
Les conditions sont listées en entier : un profil SIP joignable qui accepte les MESSAGE, enable-chat qui n'est pas false, et soit l'authentification des MESSAGE satisfaite par un compte, soit un utilisateur d'annuaire standard sans mot de passe ni a1-hash. Le processus s'exécute généralement en tant qu'utilisateur freeswitch non privilégié ; l'avis ne revendique pas root. L'impact reste le contrôle total du service de téléphonie et des données qu'il peut lire.
Pourquoi le correctif fonctionne-t-il ?
Le correctif ajoute un indicateur par profil, désactivé par défaut, et rejette le protocole api avant la distribution du message :
+ 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 comparaison est insensible à la casse pour correspondre au registre de chat, qui est créé sans sensibilité à la casse. Un MESSAGE qui sélectionne api sur un profil sans l'indicateur reçoit une réponse 403 et est journalisé avec la source et la commande demandée. Les messages sans sélecteur de protocole, ou avec un autre protocole de chat, sont routés sans changement. L'indicateur est livré commenté dans les quatre profils vanilla et dans l'exemple mod_sofia, donc la valeur par défaut est fermée. Le correctif est complet pour cette route ; il ne supprime pas l'interface de chat api, mais la place derrière une activation explicite.
Comment vérifier si j'ai été compromis ?
Aucun indicateur de compromission n'est publié. Les vérifications de cette section trouvent le motif de requête et la configuration qui rendait la route atteignable, pas une compromission confirmée :
# 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"
Avant 1.11.3, une requête réussie peut ne laisser aucun avertissement, et le journal peut n'enregistrer qu'un MESSAGE normal. Cherchez des appels sortants inattendus, de nouveaux fichiers dans le spool ou les répertoires de scripts FreeSWITCH, des dialplans modifiés, de nouveaux enregistrements SIP et toute sortie de commande que l'attaquant aurait pu recevoir. Si vous ne pouvez pas exclure une requête réussie, traitez l'hôte comme compromis, reconstruisez-le, renouvelez les identifiants SIP et de trunk, et examinez les enregistrements d'appels.
Chronologie
- 2026-08-26 : le correctif est commité dans la PR #3135, ajoutant
enable-chat-api-protoet la réponse 403. - 2026-08-28 : FreeSWITCH 1.11.3 est publié avec le correctif.
- 2026-10-28 : l'avis de sécurité GitHub est publié et indique que l'exploitation de ce chemin a été observée dans la nature.
- 2026-11-05 : CVE-2026-116779 est publiée avec CVSS v3.1 9,8.
- 2026-11-06 : la CVE n'est pas au catalogue KEV de la CISA ; aucun indicateur ni détail de victime n'est public.
FAQ
Mon FreeSWITCH est-il exposé si je n'utilise que des trunks SIP ?
Oui, si un trunk peut livrer un MESSAGE à un profil qui accepte le chat. Un compte de trunk authentifié suffit, et l'utilisateur default standard peut supprimer entièrement l'étape d'authentification. Réglez enable-chat=false sur les profils qui n'ont pas besoin du chat, ou mettez à niveau.
Cela touche-t-il les fournisseurs de PBX hébergés et de centres de contact ?
Tout fournisseur qui exécute FreeSWITCH 1.11.2 ou antérieur avec le chat entrant actif est exposé. Le correctif est dans le moteur, donc le fournisseur doit mettre à niveau ou désactiver le chat sur les profils qu'il expose. Demandez à votre fournisseur quelle version il exécute.
L'attaque est-elle non authentifiée ?
Dans la configuration standard conf/vanilla, oui, car l'utilisateur d'annuaire default n'a ni mot de passe ni a1-hash. Si cet utilisateur est supprimé et que allow-empty-password vaut false, l'attaquant a besoin d'un compte sur le profil, comme une extension ou un pair de trunk. La barre reste basse.
A-t-elle été exploitée dans la nature ?
L'avis indique que l'exploitation de ce chemin a été observée. Il ne donne ni date, ni nombre de victimes, ni indicateurs. La CVE n'est pas au catalogue KEV de la CISA au 6 novembre 2026.
disable_system_api_commands=true corrige-t-il la faille ?
Non. Cela supprime l'API system, mais la route atteint encore toutes les autres API enregistrées, y compris le chargement de modules et l'origination d'appels. Utilisez-le seulement comme mesure de réduction supplémentaire, pas comme remplacement de la mise à niveau.
Le correctif casse-t-il le chat SIP normal ?
Non. Il bloque seulement le protocole api sauf si le profil règle enable-chat-api-proto=true. Les messages sans sélecteur de protocole, ou avec un autre protocole de chat, sont routés comme avant.
Trouvez les services SIP exposés avec Ostorlab
La découverte de surface d'attaque d'Ostorlab inventorie vos hôtes exposés à Internet et les services qu'ils exposent. Utilisez-la pour lister les systèmes qui répondent sur les ports SIP, puis vérifiez d'abord leur version de FreeSWITCH et la configuration des profils.
Références
- Avis de sécurité FreeSWITCH GHSA-mg63-h38w-8p9p, publié le 28 octobre 2026, la cause racine, les configurations concernées, les contournements et la déclaration d'exploitation : https://github.com/signalwire/freeswitch/security/advisories/GHSA-mg63-h38w-8p9p (vérifié le 6 novembre 2026)
- Enregistrement CVE-2026-116779, publié le 5 novembre 2026, CVSS v3.1 9.8 et la plage concernée : https://www.cve.org/CVERecord?id=CVE-2026-116779 (vérifié le 6 novembre 2026)
- Commit FreeSWITCH 7015f6a73ab3d67fed5fbfc277ecfb88a74c2a86, « Add enable-chat-api-proto to gate the api chat proto », 26 août 2026 : https://github.com/signalwire/freeswitch/commit/7015f6a73ab3d67fed5fbfc277ecfb88a74c2a86 (vérifié le 6 novembre 2026)
- Pull request FreeSWITCH #3135, le correctif et les changements des profils vanilla : https://github.com/signalwire/freeswitch/pull/3135 (vérifié le 6 novembre 2026)
- Notes de version FreeSWITCH v1.11.3, 28 août 2026, le nouveau paramètre et la limite de l'utilisateur To : https://github.com/signalwire/freeswitch/releases/tag/v1.11.3 (vérifié le 6 novembre 2026)
- Fichier
sofia_presence.cde FreeSWITCH à v1.11.2, la découpe vulnérable de l'utilisateur To : https://github.com/signalwire/freeswitch/blob/v1.11.2/src/mod/endpoints/mod_sofia/sofia_presence.c (vérifié le 6 novembre 2026) - Fichier
mod_dptools.cde FreeSWITCH à v1.11.2, l'interface de chatapietapi_chat_send(): https://github.com/signalwire/freeswitch/blob/v1.11.2/src/mod/applications/mod_dptools/mod_dptools.c (vérifié le 6 novembre 2026) - Page du projet FreeSWITCH, la déclaration qu'il alimente des opérateurs et des centres de contact : https://freeswitch.com/ (vérifié le 6 novembre 2026)
- Docker Hub,
safarov/freeswitch, 1 366 696 téléchargements, un chiffre de portée communautaire : https://hub.docker.com/r/safarov/freeswitch (vérifié le 6 novembre 2026) - GitHub,
signalwire/freeswitch, 5 283 étoiles, un chiffre de portée du dépôt : https://github.com/signalwire/freeswitch (vérifié le 6 novembre 2026) - Flux JSON du catalogue Known Exploited Vulnerabilities de la CISA, vérifié pour CVE-2026-116779 le 6 novembre 2026 (non listée) : https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (vérifié le 6 novembre 2026)