
Documenta y reproduce una falla de autenticación fail-open en SONiC gNMI donde un mapa UserAuth vacío permite escrituras gNMI Set y gNOI sin autenticación, con un entorno de laboratorio en loopback.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sonic-gnmi-noauth
SONiC gNMI f13a08e0440f - SONiC Foundation / sonic-net
NOS SONiC de la comunidad. No es Dell Enterprise SONiC. No es SonicWall SonicOS. El comité no emite CVE. gnmi-native.sh sabe que omitir --client_auth solía deshabilitar la autenticación por completo, así que cuando falta user_auth fuerza el modo cert. Fail-closed. Luego nunca pasa --ca_crt cuando los certs están ausentes. setupFlags desactiva el cert porque no hay CA. authenticate() trata el mapa vacío como éxito. Las escrituras nativas y de translib permanecen compiladas (ENABLE_NATIVE_WRITE=y). Dos conjuntos de flags de producción, mismo skip: ToR por defecto --noTLS --bind_address 127.0.0.1; SmartSwitch DPU --insecure --allow_no_client_auth, bind vacío, todas las interfaces, puerto 8080.
UserAuth vacío tras el unset del cert es gNMI Set y escrituras gNOI sin autenticar. DPU sin certs es remoto en :8080.
| ID | sin CVE todavía |
| CWE | CWE-306, CWE-287 |
| CVSS | Crítico: 9.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (DPU sin cert). El ToR por defecto es el mismo skip en 127.0.0.1:8080 (Alto, local). |
| Producto | sonic-gnmi / sonic-buildimage |
| Afectado | sonic-gnmi hasta master f13a08e0440f; launcher 9495839742e4 |
| Auth | sin autenticar |
| Licencia | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
En un SmartSwitch DPU sin certs gNMI: desde la red, TCP :8080, sin JWT, sin PAM, sin cert de cliente. Llamar a gnmi.gNMI/Set (CONFIG_DB nativo / translib). Llamar a gnoi.debug.Debug. Reiniciar. Factory reset. File.Put bajo /tmp, /var/tmp, /host.
En un ToR/leaf por defecto sin certs: cualquier proceso que pueda alcanzar 127.0.0.1:8080 hace lo mismo. El contenedor gnmi usa host net, así que ese loopback es el del host.
Eso es reescritura de configuración del switch, y comandos de host como admin, sin autenticarse. La whitelist de Debug incluye docker, config, redis-cli, sonic-installer, reboot. El admin por defecto está en docker y %sudo. No es la contraseña admin por defecto documentada. KillProcess sigue devolviendo Unauthenticated con UserAuth vacío. No uses eso como oráculo de éxito.
Leí SECURITY.md primero. sonic-net/SONiC es la wiki. El código está en los árboles hermanos sonic-net/*. Luego diez cacerías sobre esos pins: inyección CLI, auth REST, gNMI Set, hostcfgd PAM, RESTCONF, ZTP, imagen Redis/sshd/sudo, defaults de FEATURE, GCU/SSTI, DHCP/LLDP/SNMP. Sin switch en vivo. El listón era Crítico/Alto.
La mayor parte de ese listón ya está cerrada o no es por defecto. sonic-restapi es INCLUDE_RESTAPI ?= n. El launcher de producción de RESTCONF fuerza PAM. El Redis del host es 127.0.0.1 sin requirepass, lo cual es un primer salto, no un hallazgo. El contenedor gnmi no es opcional. INCLUDE_SYSTEM_GNMI = y. La FEATURE gnmi está habilitada. Host net, host pid, host userns.
No levanté una imagen sonic-vs completa. El lab es un gRPC delgado que envuelve extractos verificados por SHA256 de setupFlags y authenticate() del pin f13a08e0440f. Ambos listeners devolvieron SONIC-GNMI-NOAUTH-WITNESS con auth_enabled=false y enable_native_write=true. UserAuth con contraseña y sin creds es Unauthenticated. Ese es el skip real, no un stub que siempre tiene éxito.
Falsos caminos ya registrados: KillProcess Unauthenticated (ese RPC ya rechaza UserAuth vacío - el lab requiere el skip de authenticate() en la ruta Set); Probe OK cuando UserAuth con contraseña está activo y no hay creds (entonces el oráculo es un stub); un gadget docker de gNOI Debug, payload nsenter, reverse shell. Teatro. Apuntar esto a una caja Dell Enterprise SONiC, o a un SonicWall. Producto equivocado.
cd lab
./run.sh
Objetivo solo 127.0.0.1:18080 (ToR plaintext) y 127.0.0.1:18081 (DPU TLS-insecure). gRPC delgado, no una imagen DPU completa. Los extractos del pin se hashean en el build contra sonic-gnmi f13a08e0440f.
IOC tor-connect 127.0.0.1:18080 plaintext no-metadata
IOC tor-check witness=SONIC-GNMI-NOAUTH-WITNESS auth_enabled=false enable_native_write=true user_auth_any=false mode=tor
IOC dpu-connect 127.0.0.1:18081 tls-insecure no-client-cert no-metadata
IOC dpu-check witness=SONIC-GNMI-NOAUTH-WITNESS auth_enabled=false enable_native_write=true user_auth_any=false mode=dpu
IOC tor-negative status=UNAUTHENTICATED
IOC dpu-negative status=UNAUTHENTICATED
SUCCESS SONIC-GNMI-NOAUTH who=unauth tor=18080 dpu=18081 SONIC-GNMI-NOAUTH-WITNESS
Si UserAuth está vacío tras eliminar el cert, no sirvas Set/gNOI write, o no escuches fuera de loopback. Copia UserAuth también en la ruta --noTLS. Aprovisiona certs de servidor y una CA para que --ca_crt esté definido y el modo cert no se desactive. No ejecutes SmartSwitch DPU sin cert (--insecure --allow_no_client_auth con CA vacía) en un :8080 alcanzable. Ambos listeners deben devolver Unauthenticated para UserAuth vacío en la ruta de escritura.
telemetry.go · server.go · whitelist.go · command.gognmi-native.sh · rules/config · init_cfg.json.j2GNU Affero GPL v3.0. Ver LICENSE. Solo lab en loopback. Sin garantía.