[하루한줄] Broadcom SDK의 Buffer Overflow 취약점
URL
Swimming Upstream: Uncovering Broadcom SDK Vulnerabilities from Bug Reports
Target
- Broadcom SDK
Explain
네트워크 기기에 UPnP 서비스를 구현하는 Broadcom SDK에서 발견된 스택 및 힙 버퍼 오버플로우 취약점의 세부 정보가 공개되었습니다.
해당 취약점은 약 10년 전 Broadcom SDK를 사용한 몇몇 기기에서 이미 공개되어 패치됐지만, 근본적인 원인인 Broadcom SDK에 대한 조치가 이루어지지 않아 여전히 다른 제품에서도 존재했던 것으로 알려졌습니다. 이러한 문제는 취약점을 찾는 것뿐만 아니라 취약점의 사후 관리와 커뮤니케이션, 공개 권고로 이루어지는 취약점의 인식 또한 중요하다는 것을 시사합니다.
Stack Buffer Overflow
스택 BOF 취약점은 UPnP 검색 프로토콜이 사용하는 HTTP 형식의 UDP 프로토콜인 SSDP(Simple Service Discovery Protocol) 메시지를 처리할 때 발생합니다.
SSDP를 통해 다음 두 가지 종류의 메시지를 보낼 수 있습니다.
- M-SEARCH : 클라이언트가 네트워크에서 사용 가능한 서비스를 검색할 때 전송합니다.
- NOTIFY : UPnP 서버가 멀티캐스트 그룹에 서비스 정보의 설정 등을 알리기 위해 전송합니다.
이중 M-SEARCH 메시지는 ssdp_msearch
함수에서 처리됩니다.
int ssdp_msearch(UPNP_CONTEXT *context) {
char name[128];
...
host = context->HOST;
if (!host || strcmp(host, "239.255.255.250:1900") != 0)
return -1;
man = context->MAN;
if (!man || strcmp(man, "\\"ssdp:discover\\"") != 0)
return -1;
st = context->ST;
...
else if (memcmp(st, "uuid:", 5) == 0) { // Vuln!
/* uuid */
type = MSEARCH_UUID;
st += 5;
strcpy(name, st);
}
}
HTTP 요청의 ST
필드가 “uuid:”로 시작하는 경우 strcpy()
로 name[128]
에 ST
필드의 문자열을 복사하는데, 길이 검사가 존재하지 않아 아래와 같은 요청을 보내면 Stack Buffer Overflow가 발생합니다.
M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
ST:uuid:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
MX:2
MAN:"ssdp:discover"
Heap Buffer Overflow
UPnP는 SOAP(Simple Object Access Protocol) 요청을 UPnP 제어 서비스에 전송해 port forwarding 규칙을 설정할 수 있습니다. SOAP 요청에는 내부 클라이언트, 내부 포트, 원격 IP, 원격 포트, 프로토콜, 규칙 지속시간이 포함됩니다.
취약점은 SOAP 요청에 따라 새로운 포트를 매핑하는 upnp_portmap_add
함수에서 발생합니다.
/* Add a new port mapping entry */
int
upnp_portmap_add
(
UPNP_CONTEXT *context,
char *remote_host,
unsigned short external_port,
char *protocol,
unsigned short internal_port,
char *internal_client,
unsigned int enable,
char *description,
unsigned long duration
)
{
UPNP_PORTMAP_CTRL *portmap_ctrl;
UPNP_PORTMAP *map;
/* Get control body */
portmap_ctrl = (UPNP_PORTMAP_CTRL *)(context->focus_ifp->focus_devchain->devctrl);
/* data validation */
if (strcasecmp(protocol, "TCP") != 0 &&
strcasecmp(protocol, "UDP") != 0) {
upnp_syslog(LOG_ERR, "add_portmap:: Invalid protocol");
return SOAP_ARGUMENT_VALUE_INVALID;
}
...
/* Update database */
map->external_port = external_port;
map->internal_port = internal_port;
map->enable = enable;
map->duration = duration;
map->book_time = time(0);
strcpy(map->remote_host, remote_host);
strcpy(map->protocol, protocol);
strcpy(map->internal_client, internal_client);
strcpy(map->description, description);
...
return 0;
}
upnp_portmap_add
는 수신한 요청에 대한 유효성을 검증하고 기존에 설정된 port map이 없으면 새 port map 구조체를 할당합니다. 새로운 port map 구조체를 설정하는 과정에서 strcpy()
함수를 사용하고 길이 검증을 하지 않아 Heap Buffer Overflow가 발생합니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.