[하루한줄] CVE-2020-8277: Node.js OOB Read를 통한 Denial of Service

URL

CVE-2020-8277 Analysis: From Node.JS code to OOB Reads/Fail-Check

Target

  • Node.js
    • < 15.2.1
    • < 14.15.1
    • < 12.19.1

Explain

Node.js에서 OOB(Out of Bounds) Read를 통해 Denial of Service를 트리거할 수 있는 취약점이 발견되었습니다. 해당 취약점은 많은 양의 DNS record를 c-ares 라이브러리에서 TTL record를 parsing 할 때 배열 길이의 계산을 잘못하면서 일어나는 취약점입니다.

c-ares 라이브러리의 ares_parse_aaaa_reply 함수는 response를 포함하는 char* abuffer, response의 길이인 alen, DNS response가 반환될 구조체 포인터 host, TTL 배열인 addrttls / naddrttls를 인자로 갖습니다. addrttls는 반환된 TTL의 주소로 채워지는 배열이고, naddrttls는 반환할 TTL의 최대 값입니다. response의 reply 개수가 addrttls 배열보다 클 경우 naddrttls에서 확인 후 256개의 TTL만 처리되고 나머지 부분은 잘리게 됩니다. 하지만 취약점은 TTL의 개수에 대한 잘못된 처리가 아니라 response의 reply 개수를 잘못 계산하는 것에서 일어납니다.

  1. reply의 개수를 새서 naddrs에 저장
  2. TTL 배열 작성(naddrttls에 의해 잘린 addrttls)
  3. naddrttls 재작성 - 실제 TTL 배열에 작성된 값보다 큰 지 확인하지 않고 naddrs를 집어넣음

따라서 반환된 naddrttls가 작성된 reply의 TTL 개수보다 커지므로 OOB read가 가능하고 이를 악용하여 Denial of Service 공격을 트리거할 수 있습니다.

해당 취약점은 naddrttlsnaddrs 값을 넣을 때 naddrs의 값이 naddrttls보다 클 경우 naddrttls 값을 넣는 것으로 패치되었습니다.

if(naddrttls)
{
	*naddrttls = (naddrs > *naddrsttls) ? *naddrttls:naddrs;
}