
SONiC gNMI에서 빈 UserAuth 맵이 인증되지 않은 gNMI Set 및 gNOI 쓰기를 허용하는 fail-open 인증 결함을 문서화하고 재현하며, 루프백 랩 하네스를 포함합니다.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sonic-gnmi-noauth
SONiC gNMI f13a08e0440f - SONiC Foundation / sonic-net
커뮤니티 SONiC NOS. Dell Enterprise SONiC가 아니다. SonicWall SonicOS도 아니다. 위원회는 CVE를 발급하지 않는다. gnmi-native.sh는 --client_auth를 생략하면 인증이 완전히 비활성화된다는 것을 알고 있으므로, user_auth가 없으면 인증서 모드를 강제한다. Fail-closed. 그런데 인증서가 없을 때 --ca_crt를 전혀 전달하지 않는다. setupFlags는 CA가 없기 때문에 인증서를 unset한다. authenticate()는 빈 맵을 성공으로 취급한다. Native 및 translib 쓰기는 컴파일된 상태로 남아 있다(ENABLE_NATIVE_WRITE=y). 두 가지 프로덕션 플래그 세트, 동일한 skip: 기본 ToR --noTLS --bind_address 127.0.0.1; SmartSwitch DPU --insecure --allow_no_client_auth, 빈 bind, 모든 인터페이스, 포트 8080.
인증서 unset 이후 빈 UserAuth는 인증되지 않은 gNMI Set 및 gNOI 쓰기다. 인증서가 없는 DPU는 :8080에서 원격이다.
| ID | 아직 CVE 없음 |
| CWE | CWE-306, CWE-287 |
| CVSS | Critical: 9.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (DPU no-cert). 기본 ToR은 127.0.0.1:8080에서 동일한 skip (High, local). |
| Product | sonic-gnmi / sonic-buildimage |
| Affected | sonic-gnmi through master f13a08e0440f; launcher 9495839742e4 |
| Auth | unauthenticated |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
gNMI 인증서가 없는 SmartSwitch DPU에서: 네트워크로부터, TCP :8080, JWT 없음, PAM 없음, 클라이언트 인증서 없음. gnmi.gNMI/Set 호출 (native CONFIG_DB / translib). gnoi.debug.Debug 호출. 재부팅. 공장 초기화. /tmp, /var/tmp, /host 아래 File.Put.
인증서가 없는 기본 ToR/leaf에서: 127.0.0.1:8080에 접근할 수 있는 모든 프로세스가 동일한 작업을 수행한다. gnmi 컨테이너는 host net이므로 그 loopback은 호스트의 것이다.
즉, 인증 없이 스위치 설정 재작성과 admin으로서의 호스트 명령 실행이다. Debug 화이트리스트에는 docker, config, redis-cli, sonic-installer, reboot가 포함된다. 기본 admin은 docker와 %sudo에 속한다. 문서화된 기본 admin 비밀번호가 아니다. KillProcess는 빈 UserAuth에서 여전히 Unauthenticated를 반환한다. 그것을 성공 판별 기준으로 사용하지 마라.
먼저 SECURITY.md를 읽었다. sonic-net/SONiC는 위키다. 코드는 형제 sonic-net/* 트리다. 그런 다음 해당 핀들에 대해 열 번의 사냥: CLI injection, REST auth, gNMI Set, hostcfgd PAM, RESTCONF, ZTP, image Redis/sshd/sudo, FEATURE defaults, GCU/SSTI, DHCP/LLDP/SNMP. 라이브 스위치는 없었다. 기준은 Critical/High였다.
그 기준의 대부분은 이미 닫혀 있거나 기본값이 아니다. sonic-restapi는 INCLUDE_RESTAPI ?= n이다. RESTCONF의 프로덕션 런처는 PAM을 강제한다. 호스트 Redis는 requirepass 없이 127.0.0.1에 있으며, 이는 첫 번째 홉일 뿐 발견 사항이 아니다. gnmi 컨테이너는 선택 사항이 아니다. INCLUDE_SYSTEM_GNMI = y. FEATURE gnmi가 활성화되어 있다. Host net, host pid, host userns.
전체 sonic-vs 이미지를 세우지는 않았다. 랩은 핀 f13a08e0440f의 setupFlags와 authenticate()를 SHA256 검증된 추출물로 감싼 얇은 gRPC다. 두 리스너 모두 auth_enabled=false와 enable_native_write=true로 SONIC-GNMI-NOAUTH-WITNESS를 반환했다. 자격 증명 없는 비밀번호 UserAuth는 Unauthenticated다. 그것이 실제 skip이며, 항상 성공하는 스텁이 아니다.
이미 기록된 잘못된 방향: KillProcess Unauthenticated (그 RPC는 이미 빈 UserAuth를 거부한다 - 랩은 Set-path authenticate() skip을 요구한다); 비밀번호 UserAuth가 켜져 있고 자격 증명이 없을 때 Probe OK (그러면 판별 기준이 스텁이다); gNOI Debug docker gadget, nsenter payload, reverse shell. 연극이다. 이것을 Dell Enterprise SONiC 박스나 SonicWall에 겨누는 것. 잘못된 제품이다.
cd lab
./run.sh
오직 127.0.0.1:18080 (ToR plaintext)과 127.0.0.1:18081 (DPU TLS-insecure)만 대상으로 한다. 얇은 gRPC이며, 전체 DPU 이미지가 아니다. 핀 추출물은 빌드 시 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
인증서를 제거한 후 UserAuth가 비어 있으면 Set/gNOI 쓰기를 제공하지 말거나, loopback 외부에서 리스닝하지 마라. --noTLS 경로에서도 UserAuth를 복사하라. 서버 인증서와 CA를 프로비저닝하여 --ca_crt가 설정되고 인증서 모드가 unset되지 않도록 하라. 접근 가능한 :8080에서 인증서 없는 SmartSwitch DPU(--insecure --allow_no_client_auth와 빈 CA)를 실행하지 마라. 쓰기 경로에서 빈 UserAuth에 대해 두 리스너 모두 Unauthenticated를 반환해야 한다.
telemetry.go · server.go · whitelist.go · command.gognmi-native.sh · rules/config · init_cfg.json.j2GNU Affero GPL v3.0. LICENSE 참조. Loopback 랩 전용. 보증 없음.