
Veeam Service Provider Console 인증 우회 CVE-2026-58073을 안전하게 탐지합니다.
Veeam Service Provider Console의 KB4893 취약점(2026-08-04 게시)을 위한 안전하고 인증이 필요 없는 탐지 도구입니다. 인증이나 TLS 이전에 각 대상에 대해 단 하나의 질문에 답합니다: 이 콘솔에 KB4893 수정 사항이 적용되었는가?
핵심 취약점 쌍은 체인 형태입니다. CVE-2026-58073(CVSS 9.5)은 인증되지 않은 네트워크 피어가 연결된 관리 에이전트를 가장하고 해당 에이전트의 실제 인증서를 발급받을 수 있게 합니다. 에이전트 핸드셰이크가 피어가 자신의 인증서에 기록한 GUID로 권한을 결정하기 때문입니다. CVE-2026-58072(CVSS 9.0)는 에이전트 신원을 확보한 후 도달할 수 있는 임의 파일 쓰기 취약점입니다. 체인으로 연결되면 모든 테넌트의 백업을 관리하는 콘솔에서 인증 없는 원격 코드 실행이 가능합니다. 동일한 권고에서 CVE-2026-58071(CVSS 8.2, Portal Administrator로 프록시된 어플라이언스 API)과 CVE-2026-58067(CVSS 8.7, 인증 없는 메모리 고갈 DoS)도 수정되었습니다. CVE-2026-58073과 CVE-2026-58072는 HackerOne을 통해 Veeam에 보고되었으며, 권고에는 보고자의 이름이 명시되지 않았습니다.
이 스크립트는 가장을 시도하거나, 인증서를 요청하거나, 파일을 쓰지 않습니다. 라우터가 광고하는 프로토콜 세대만 읽습니다.
네. 이 탐지 도구는 프로덕션 및 평가 용도로 설계되었습니다:
Connector 핸드셰이크만 전송합니다. TLS 세션이 협상되지 않고, 인증서가 제시되지 않으며, SaveFiles는 절대 호출되지 않습니다.ChannelHostProxy.m_multiplexers에서 실패한 사전 조회입니다. 수신자가 등록되지 않고, 채널이나 멀티플렉서가 구축되지 않으며, 에이전트 레코드가 변경되지 않습니다. Receiver 유형 핸드셰이크는 이름을 등록하지만, 이 도구는 절대 전송하지 않습니다.ConnectionHub.log의 여섯 줄이며, 각 줄에는 bf-probe-<uuid4> 수신자 이름이 포함되어 방어자가 스캔과 공격을 구분할 수 있습니다. 정확한 줄은 아래에 있습니다.VULNERABLE로 보고됩니다(아래 참조). 따라서 조용한 TCP 서비스가 패치되지 않은 콘솔로 오인될 수 없습니다.대상당 도구는 두 개의 TCP 연결을 열고 각각에 존재하지 않는 bf-probe-<uuid4> 수신자를 지정하는 ConnectionHub 핸드셰이크를 하나씩 전송합니다.
기본 --transport auto에서 포트가 암시하는 전송 방식과 다른 대상을 사용하면 연결이 하나 더 추가됩니다: 잘못된 전송 방식의 프로브는 수신자 이름이 읽히기 전에 핸드셰이크 중에 거부되고, 올바른 전송 방식이 두 실제 프로브에 사용됩니다. 정확히 두 연결로 유지하려면 --transport direct 또는 --transport gateway를 지정하세요 — 변경 요청에 연결 수를 명시한 경우 유용합니다.
서버 상태 변경: 없음. Connector 코드 경로는 ChannelHostProxy.m_multiplexers에서 사전 조회를 수행하고, 실패하여 오류를 반환합니다. 수신자가 등록되지 않고, 멀티플렉서나 채널이 생성되지 않으며, TLS 세션이 협상되지 않고, 에이전트 레코드가 변경되지 않습니다. 이 도구는 이름을 등록하는 Receiver 유형 핸드셰이크를 절대 전송하지 않습니다.
로그 항목은 %ProgramData%\Veeam\Veeam Availability Console\Log\Server\ConnectionHub.log에 기록됩니다. 라이브 9.2.1.33875 ConnectionHub에서 그대로 가져온 것으로, 타임스탬프와 범위 JSON은 생략되었습니다:
프로브 1(버전 6), 패치 및 미패치 빌드 모두:
[INFO] ChannelHostProxy: Accept connection begin {"RemoteEndPoint":"<ip>:<port>","Line":"1"}
[INFO] ChannelHostProxy: Accept connection end {"RemoteEndPoint":"<ip>:<port>","Line":"2",...}
[WARN] ChannelHostProxy: Cannot connect transmitter. Requested receiver not found
(receiver name:bf-probe-<uuid>) {"RemoteEndPoint":"<ip>:<port>","Line":"3",...}
프로브 2(버전 7), 패치 빌드만:
동일한 세 줄
프로브 2(버전 7), 미패치 빌드:
[INFO] ChannelHostProxy: Accept connection begin
[WARN] ChannelHostProxy: Handshake failed. Reason:Unsupported client version "7"
[INFO] ChannelHostProxy: Accept connection end
두 연결, 여섯 줄, 다른 항목 없음, 상태 변경 없음 — 라이브 호스트에서 확인되었습니다.
ConnectionHub.log의 리터럴 문자열 bf-probe-는 이 도구의 트래픽을 식별하므로 방어자가 귀속시킬 수 있고 스캔 팀이 보낸 내용을 증명할 수 있습니다. 다른 마커가 필요하면 소스의 RECEIVER_PREFIX를 변경하세요.
ConnectionHub 관리 에이전트 라우터는 인증이나 TLS 이전에 클라이언트 핸드셰이크를 읽고, Request.Read는 클라이언트가 광고한 프로토콜 버전을 하드코딩된 범위와 대조하여 검증합니다. 수정 사항은 CVE를 수정한 동일한 빌드에서 해당 범위를 확장했습니다:
| 빌드 | 검사 | 허용 |
|---|---|---|
<= 9.2.1.33875 (취약) | (uint)(versionByte - 3) <= 3 | 3, 4, 5, 6 |
>= 9.3.0.35057 (패치됨) | (uint)(versionByte - 3) <= 4 |
따라서 버전 7을 광고하는 핸드셰이크는 깔끔한 이진 판별자입니다. 탐지 도구는 대상당 두 개의 프로브를 보내며, 순서에는 이유가 있습니다(전송 감지는 세 번째를 추가할 수 있음 — 아래 참조):
| 프로브 | 광고 | 목적 |
|---|---|---|
| 1 | 버전 6 | Requested receiver not found를 반환해야 하며, 대상이 실제 VSPC ConnectionHub임을 증명 |
| 2 | 버전 7 | 응답이 있으면 PATCHED, 침묵이면 VULNERABLE |
1단계 게이트가 없으면 프로브 2의 침묵은 인터넷의 조용한 TCP 서비스와도 일치하며, 방화벽이 취약한 Veeam 콘솔로 보고될 수 있습니다.
관리 에이전트가 사용하는 두 경로 모두에서 작동합니다:
| 전송 방식 | 포트 | 노출 |
|---|---|---|
| ConnectionHub 직접 | 9999 | 일반적으로 내부 |
| Veeam Cloud Connect 게이트웨이 경유 | 6180 | 설계상 인터넷 노출 |
게이트웨이 경로에는 직접 경로에는 없는 릴레이 프롤로그가 필요하므로 프로브 1이 전송 감지를 겸합니다. 기본 --transport auto에서는 한 전송 방식을 시도하고, 핑거프린트 게이트가 통과하지 않으면 다른 방식을 시도합니다. 통과하는 방식은 래치되고 프로브 2가 이를 재사용합니다 — 혼합 대상 파일에 호스트별 주석이 필요 없습니다.
래치는 중요합니다. 프로브 2가 다른 전송 방식으로 재시도할 수 있다면 침묵이 더 이상 버전 검사에 귀속되지 않고 "두 바이트 경로 중 하나가 응답하지 않음"에만 귀속되어 거짓 VULNERABLE이 생성될 수 있습니다.
먼저 시도할 전송 방식은 포트에 의해 결정되며, 이는 단순한 장식이 아닙니다 — 두 불일치는 매우 다른 속도로 실패합니다:
| 불일치 | 원격 측의 해석 | 비용 |
|---|---|---|
| 릴레이 프롤로그 → 직접 허브 | hostType 44 / versionByte 0의 int16 메타, Request.Read의 범위 검사 실패 | 한 왕복에 처리됨 |
| 직접 핸드셰이크 → 게이트웨이 | 1,012,729,346의 int32 프레임 길이 | 게이트웨이가 도착하지 않는 바이트를 기다림; 전체 타임아웃 소모 |
따라서 auto는 포트를 소유한 서비스로 시작합니다: 6180에서는 게이트웨이 우선, 그 외에는 직접 우선. 이렇게 하면 일반적인 경우는 단일 시도로 유지되고 비용이 큰 불일치가 빠른 경로에서 제외됩니다. TCP를 전혀 열지 못하는 프로브는 두 번째 전송 방식을 시도하지 않고 단락되므로, 넓은 스윕에서 죽은 호스트는 두 번이 아닌 한 번의 타임아웃만 소모합니다.
VULNERABLE은 "KB4893 수정 사항이 없음"을 의미하며 "이것이 9.2.1.33875임"을 의미하지 않습니다. 9.2.1보다 오래된 빌드는 동일한 버전 검사를 공유하므로 프로토콜 6을 보고하고 취약한 것으로 보고되어야 합니다(코드에서 추론, 측정 아님 — 제한 사항 참조). 그러나 도구는 9.2.1과 9.1 또는 8.1을 구분할 수 없습니다. 정확한 빌드가 필요하면 콘솔 UI에서 확인하세요.
# 단일 호스트(기본 TCP/9999)
./cve_2026_58073_check.py vspc.example.com
# 명시적 포트, 여러 호스트
./cve_2026_58073_check.py vspc.example.com:9999 10.0.0.5
# 목록 스캔, 줄당 하나의 대상('#' 주석 허용), 간결한 출력
./cve_2026_58073_check.py -f targets.txt --brief
# 파이프라인용 기계 판독 가능 출력
./cve_2026_58073_check.py -f targets.txt --json > results.json
# Veeam Cloud Connect 게이트웨이 — 릴레이 전송 방식은 자동 감지됨
./cve_2026_58073_check.py cc-gw.example.com:6180
# 전송 방식을 고정하여 감지 건너뛰기(포트는 6180으로 기본 설정)
./cve_2026_58073_check.py --transport gateway cc-gw.example.com
# 네트워크 액세스 없이 와이어 코덱 검증
./cve_2026_58073_check.py --self-test
패치되지 않은 콘솔(기본 두 줄 출력). [!] 마커와 VULNERABLE은 TTY에서 빨간색으로 표시됩니다:
$ ./cve_2026_58073_check.py vspc.example.com
[!] vspc.example.com:9999: VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
패치된 콘솔:
$ ./cve_2026_58073_check.py patched.example.com
[+] patched.example.com:9999: PATCHED [protocol-7-accepted]
ConnectionHub accepts protocol 7, so the KB4893 fixes are present (>= 9.3.0.35057)
게이트웨이 대상, 릴레이 전송 방식이 자동 감지됨. (gateway) 접미사는 판정이 이루어진 전송 방식을 나타냅니다:
$ ./cve_2026_58073_check.py cc-gw.example.com:6180
[!] cc-gw.example.com:6180 (gateway): VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
에스테이트 스윕, 호스트당 하나의 정렬 줄(--brief). 호스트가 하나라도 VULNERABLE이면 종료 상태는 1, 그렇지 않으면 0 — 스크립트에 유용:
$ ./cve_2026_58073_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE vspc.example.com:9999 protocol-7-rejected
PATCHED patched.example.com:9999 protocol-7-accepted
UNAFFECTED fileserver.example.com:9999 not-vspc
ERROR unused.example.com:9999 unreachable
exit: 1
파이프라인용 기계 판독 가능 출력(--json). 대상당 모든 프로브가 포함되므로 증거에서 판정을 다시 도출할 수 있습니다. transport는 판정이 이루어진 전송 방식이며, 각 프로브는 사용된 전송 방식을 포함합니다 — 따라서 자동 감지된 대상은 거부된 시도도 표시합니다:
$ ./cve_2026_58073_check.py vspc.example.com --json
[
{
"target": "vspc.example.com:9999",
"host": "vspc.example.com",
"port": 9999,
"transport": "direct",
"verdict": "VULNERABLE",
"reason": "protocol-7-rejected",
"detail": "ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)",
"protocol_version": 6,
"affected_cves": [
"CVE-2026-58073",
"CVE-2026-58072",
"CVE-2026-58071",
"CVE-2026-58067"
],
"probes": [
{
"version_byte": 6,
"transport": "direct",
"connected": true,
"responded": true,
"status": "Error",
"message": "Cannot connect transmitter. Requested receiver not found (receiver name:bf-probe-b7c40be0-e2e8-41dc-9fc3-cbbd7345954a)",
"error": ""
},
{
"version_byte": 7,
"transport": "direct",
"connected": true,
"responded": false,
"status": "",
"message": "",
"error": ""
}
]
}
]
| 코드 | 의미 |
|---|---|
0 | VULNERABLE 대상 없음 |
1 | 최소 하나의 대상이 VULNERABLE |
2 | 사용법 오류(잘못된 인수 / 읽을 수 없는 대상 파일) |
--transport auto의 게이트웨이 구간에도 적용됩니다. 테스트되지 않은 경로를 스윕에서 완전히 제외하려면 --transport direct를 지정하세요.VULNERABLE 판정은 패치 상태를 말하며, 콘솔이 악용되었는지 여부는 말하지 않습니다. 악용은 패치 및 미패치 빌드 모두에서 콘솔 로그에 자체 흔적을 남깁니다. 별도로 조사하세요.Veeam Service Provider Console 9.3.0.35057 이상으로 업그레이드하세요(KB4893). 네 가지 문제 모두 해당 빌드 하나에서 수정되며 9.2.x 백포트가 없으므로 해결 방법은 핫픽스가 아닌 버전 업그레이드입니다.
업그레이드가 수행하지 않는 두 가지가 있습니다. TCP/9999에 도달할 수 있는 대상을 제한하지 않으므로 관리 에이전트가 있는 서브넷만 응답해야 합니다. 또한 콘솔이 이미 발급한 에이전트 인증서(미패치 상태에서 공격자에게 발급된 인증서 포함)를 취소하지 않습니다. 악용 증거를 발견하면 손상된 에이전트 인증서에 대한 지침을 위해 Veeam 지원 케이스를 여세요: 인증서 교체는 문서화된 절차가 아니며, 포털에서 관리할 수 있는 인증서는 에이전트 인증서에 서명하는 CA가 아닙니다.
이 코드는 MIT 라이선스에 따라 배포됩니다.
사전 상호 동의 없이 대상을 공격하기 위해 이 도구를 사용하는 것은 불법입니다. 모든 해당 지역, 주, 연방 법률을 준수하는 것은 최종 사용자의 책임입니다. 개발자는 이 프로그램으로 인한 오용이나 손해에 대해 책임을 지지 않습니다.
| 3, 4, 5, 6, 7 |
| 플래그 | 설명 |
|---|
targets | 하나 이상의 HOST[:PORT](포트 기본값 9999, --transport gateway 사용 시 6180) |
-f, --targets-file FILE | 파일에서 대상 읽기(줄당 하나; # 주석) |
--transport {auto,direct,gateway} | ConnectionHub에 도달하는 방법. auto(기본값)는 대상별로 감지; gateway는 Cloud Connect 릴레이 프롤로그를 앞에 추가하고 포트 기본값을 6180으로 설정 |
-p, --port PORT | 기본 포트 재정의 |
--timeout SECS | 프로브당 타임아웃(기본값: 8) |
--workers N | 동시 대상 수(기본값: 16); 출력은 입력 순서 유지 |
-b, --brief | 대상당 단일 정렬 줄 — 많은 호스트 스캔에 이상적 |
--json | 대상당 전송된 모든 프로브를 포함한 구조화된 JSON 출력 |
--no-color | 색상 출력 비활성화(NO_COLOR 및 비-TTY도 인식) |
--self-test | .NET 와이어 코덱 검증 후 종료; 네트워크 액세스 없음 |
| 판정 | 이유 태그 | 의미 |
|---|
VULNERABLE | protocol-7-rejected | 프로토콜 6을 허용하고 7을 거부하는 확인된 VSPC ConnectionHub. KB4893 수정 사항이 없음(<= 9.2.1.33875). |
PATCHED | protocol-7-accepted | 프로토콜 7을 허용하는 확인된 VSPC ConnectionHub. KB4893 수정 사항이 있음(>= 9.3.0.35057). |
UNAFFECTED | not-vspc | TCP를 수락했지만 시도한 어떤 전송 방식에서도 유효한 ConnectionHub 핸드셰이크에 응답하지 않음 — VSPC ConnectionHub가 아님. |
INCONCLUSIVE | unexpected-reply | 핑거프린트 프로브에 Requested receiver not found가 아닌 다른 응답을 반환. |
INCONCLUSIVE | inconclusive-discriminator | 핑거프린트 게이트를 통과한 후 버전 7 프로브에 통과도 실패도 아닌 방식으로 응답 — 또는 두 번째 연결이 완전히 실패. 재시도. |
ERROR | unreachable | 연결할 수 없거나, Cloud Connect 게이트웨이가 첫 번째 시도한 전송 방식에서 릴레이 프롤로그를 거부(auto에서는 포트 6180의 모든 대상을 의미). |