[하루한줄] OpenBSD의 Heap Buffer Overflow 취약점
URL
Heap Overflow in OpenBSD’s slaacd via Router Advertisement
Target
- OpenBSD 6.9, 7.0
Explain
OpenBSD의 IPv6 스택 중 라우터 요청 메시지를 보내고 수신된 라우터 알림 응답을 파싱하는 SLAAC(Stateless Address Autoconfiguration) 데몬인 slaacd 에서 Heap Buffer Overflow 취약점이 발견되었습니다.
Router Advertisement(RA)는 IPv6 프로토콜 스택 중 Neighbeor Discovery(ND) 프로토콜의 메시지 타입 중 하나이며 링크 및 인터넷 매개변수와 함께 라우터가 있음을 알리는 역할을 합니다. RA 패킷에는 DNS 검색 목록(DNSSL)이 포함되는데, 이 DNSSL을 파싱하는 sbin/slaacd/engine.c
의 parse_dnssl
함수에서 취약점이 발견되었습니다.
char* parse_dnssl(char* data, int datalen) {
int len, pos; // [1]
char *nssl, *nsslp;
if((nssl = calloc(1, datalen + 1)) == NULL) {
log_warn("malloc");
return NULL;
}
nsslp = nssl;
pos = 0;
do {
len = data[pos]; // [2]
if (len > 63 || len + pos + 1 > datalen) { //[3]
free(nssl);
log_warnx("invalid label in DNSSL");
return NULL;
}
if (len == 0) {
if (pos < datalen && data[pos + 1] != 0)
*nsslp++ = ' '; /* seperator for next domain */
else
break;
} else {
if (pos != 0 && data[pos - 1] != 0) /* no . at front */
*nsslp++ = '.';
memcpy(nsslp, data + pos + 1, len); // [4]
nsslp += len;
}
pos += len + 1;
} while(pos < datalen);
if (len != 0) {
free(nssl);
log_warnx("invalid label in DNSSL");
return NULL;
}
return nssl;
}
취약점은 레이블의 길이 필드를 읽을 때 signed 정수인 len
을 사용해 발생합니다.
[1] : signed 정수 int len
을 선언합니다.
[2]: 레이블에 음수가 포함되면 len
이 음수가 됩니다.
[3]: 음수 len
으로 인해 길이 검사를 우회할 수 있습니다.
[4]: memcpy()
에 전달되는 세 번째 인수 포맷은 unsigned인 size_t
이기 때문에 묵시적 형 변환으로 인해 INT_MAX
값이 전달되어 예상보다 큰 길이를 복사하게 되고, 이는 nsslp
버퍼의 heap buffer overflow로 이어집니다.
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.