
libiec61850 v1.6의 GOOSE 재생 처리에 영향을 주는 CVE-2026-52134에 대한 공개 기술 권고 및 재현 증거
CVE-2026-52134이(가) 배정되었습니다. 해당 CVE 레코드의 공개는 보류 중입니다.
src/goose/goose_receiver.cparseGoosePayload()libiec61850 v1.6의 GOOSE 구독자 수신 경로는 구독자에게 보이는 상태를 업데이트하고 등록된 리스너 콜백을 호출하기 전에 특정 재생 또는 오래된 GOOSE 메시지를 적절히 거부하지 않습니다.
두 가지 통제된 실험이 동일한 수신 경로에서 관련 동작을 보여줍니다:
stNum 롤백: 구독자가 stNum=2를 처리한 후, 이전에 캡처한 stNum=1 프레임을 재생하면 리스너가 이전 상태와 데이터를 다시 보고했습니다.sqNum 재생: 동일한 stNum을 가지지만 더 오래된 sqNum을 가진 이전에 캡처한 프레임이 재생되었을 때, 해당 프레임은 유효하지 않음으로 표시되었지만 리스너 콜백은 계속 발생했고 재생된 데이터는 계속 표시되었습니다.이는 두 개의 별도 CVE가 아니라 하나의 재생/메시지 신선도 처리 문제에 대한 두 가지 관련 관찰 결과로 제시됩니다.
공격자는 다음을 할 수 있어야 합니다:
0x88B8을 사용하여 이더넷 프레임 주입이는 임의의 인터넷 기반 원격 공격이 아닙니다.
관련 수신 로직은 수신된 stNum이 저장된 stNum과 같을 때 sqNum을 확인합니다. 테스트된 코드 경로는 구독자 상태가 업데이트되고 리스너가 호출되기 전에 더 낮은 stNum을 거부하지 않습니다.
테스트된 라이브러리 파일은 수정되지 않았습니다. src/goose/goose_receiver.c의 원본과 작업 복사본은 동일한 SHA-256 값을 가졌습니다:
c42f2aec80f605c458d0bca524ccb09f2e35f9b83a02f854f95d9444616c075b

veth0 / veth1 격리된 가상 이더넷 페어tcpdump테스트 하네스는 통제된 상태 전이를 생성하고 콜백에서 볼 수 있는 stNum, sqNum, 유효성 및 데이터 값을 출력했습니다. 취약한 라이브러리 파일 자체는 수정되지 않았습니다.
통제된 퍼블리셔가 두 가지 상태를 전송했습니다:
State A: stNum=1, sqNum=0, data=1111
State B: stNum=2, sqNum=0, data=2222
기준 패킷 캡처에는 이 순서대로 두 개의 GOOSE 프레임이 포함되어 있었습니다:
Frame 1: stNum=1, sqNum=0
Frame 2: stNum=2, sqNum=0

구독자 출력에는 State B 이전에 valid=false로 표시된 stNum=1, sqNum=0에 대한 보조 콜백도 포함되어 있었습니다. 이 보조 콜백은 증거 자료에 포함되어 있지만 롤백 결론의 근거로 사용되지는 않습니다. 재생 전 결정적 상태는 stNum=2와 데이터 값 2222를 포함한 이후의 콜백이었습니다.
재생 스크립트는 두 프레임 기준 캡처를 로드하고 프레임 1을 선택한 후 이를 veth0을 통해 한 번 전송했습니다.
재생 직전에 리스너는 다음을 보고했습니다:
stNum=2, sqNum=0, valid=true, allData={2222}
이전 프레임이 한 번 재생된 후 리스너는 다음을 보고했습니다:
stNum=1, sqNum=0, valid=true, allData={1111}

이는 이전에 캡처한 더 낮은 stNum 프레임을 재생한 후 stNum=2에서 stNum=1로의 구독자 상태 롤백이 관찰되었음을 보여줍니다.
동일한 이전 프레임의 사본 4개가 더 전송되었습니다. 네 개 모두 stNum=1, sqNum=0을 포함했습니다.
이후의 사본들은 valid=false로 보고되었지만 콜백 번호는 계속 증가했고 재생된 데이터는 계속 표시되었습니다:

이 보조 관찰 결과는 반복된 프레임을 유효하지 않음으로 표시해도 테스트된 수신 경로에서 리스너 전달을 막지 못한다는 것을 보여줍니다.
이전 재현에서는 공식 예제 퍼블리셔와 구독자를 사용했습니다. 퍼블리셔는 다음의 정상적인 시퀀스를 생성했습니다:
stNum=1
sqNum=0, 1, 2, 3
그런 다음 구독자가 이후의 시퀀스 값을 이미 처리한 후 첫 번째 캡처 프레임(stNum=1, sqNum=0)이 재생되었습니다.

수신된 sqNum=0이 저장된 시퀀스 값보다 새롭지 않았기 때문에 재생된 사본들은 유효하지 않음으로 보고되었습니다. 그러나 구독자는 재생된 데이터를 포함한 리스너 이벤트를 계속 출력했습니다:

이 실험은 더 제한적이지만 관련된 관찰 결과를 뒷받침합니다:
원본 재생의 원시 스크린샷은 보조 자료로 보존됩니다:
이 원시 이미지에는 관련 없는 Scapy 선택적 모듈 가져오기 경고가 포함되어 있습니다. 경고는 스크립트가 캡처된 GOOSE 프레임을 보고하고 전송을 완료하는 것을 막지 못했지만, 기술적 결과를 검토할 때에는 위의 더 깔끔한 스크린샷이 선호됩니다.
실험은 동일한 GOOSE 재생/메시지 신선도 문제의 서로 다른 분기를 보여줍니다:
| 관찰 | 수신 메시지 | 관찰된 결과 |
|---|---|---|
낮은 stNum 재생 | 저장된 stNum=2; 이전 stNum=1 수신 | 이전 상태와 데이터가 리스너에게 전달되었고 테스트 실행에서 유효한 것으로 보고됨 |
비증가 sqNum 재생 | 동일한 stNum; 더 오래되거나 중복된 sqNum 수신 | 메시지가 유효하지 않음으로 보고되었지만 리스너 콜백과 재생 데이터 전달은 계속됨 |
첫 번째 관찰 결과는 최신 상태에서 이전 상태로의 롤백을 보여주기 때문에 주요 CVE 발견 사항입니다. 두 번째 관찰 결과는 유효하지 않은 동일 상태 재생이 리스너 경로를 통해 계속 전달되는 방식에 대한 지원 증거입니다.
시연된 소프트웨어 수준 영향은 다음과 같습니다:
stNum에서 이전 stNum으로 이동할 수 있습니다.콜백 데이터를 독립적인 신선도 강제 없이 사용하는 애플리케이션은 오래되었거나 재생된 값을 처리할 수 있습니다.
다운스트림 영향은 구독자 애플리케이션, 구성, 인터록 로직 및 보호 로직에 따라 달라집니다.
이 실험에서는 물리적 보호 계전기, 트립 회로, 차단기 또는 실제 변전소 네트워크가 테스트되거나 운영되지 않았습니다.
구독자 상태를 업데이트하거나 리스너를 호출하기 전에:
stNum보다 오래된 수신 stNum을 거부합니다.stNum이 변경되지 않은 경우 비증가 sqNum을 거부합니다.stNum 롤백 및 반복된 sqNum 값을 모니터링합니다.다음 이미지는 출처와 환경 정보를 제공합니다. 이는 재현을 뒷받침하지만 주요 결과를 이해하는 데 개별적으로 필요하지는 않습니다.





시연된 결과는 재생 수용 및 오래된 상태 전달입니다. 이는 테스트된 배포에서 암호화 인증이 활성화되었음을 증명하는 것에 의존하지 않습니다.
보고자: