Impact
The DNS code in the Zephyr RTOS contains a possible out of bounds read which can potentially result in remote code execution.
possible read out of bounds in dns_read() in resolve.c. They unpack header id and check qr bit before they unpack the entire header.
in function dns_unpack_response_query() there is this code snippet:
/* 4 bytes more due to qtype and qclass */
offset += DNS_QTYPE_LEN + DNS_QCLASS_LEN;
if (offset > dns_msg->msg_size) {
return -ENOMEM;
}
what if (offset == dns_msg->msg_size)? we'll have a read out of bounds.
The following snippet of code appears in the function dns_unpack_answer() is called after skip_fqdn(). I think this check is faulty, since msg_size
contains the actual size of the whole DNS message and it is not changed before hand as far as i've seen.
rem_size = dns_msg->msg_size - dname_len;
if (rem_size < 2 + 2 + 4 + 2) {
return -EINVAL;
}
Read out-of-bounds in dns_read() if RDLENGTH is bigger than the actual. Also we can uninitialized bytes in src
:
memcpy(addr, src, address_size);
Wrong update of the answer resource record:
/* Update the answer offset to point to the next RR (answer) */
dns_msg.answer_offset += DNS_ANSWER_PTR_LEN;
dns_msg.answer_offset += dns_msg.response_length;
DNS_ANSWER_PTR_LEN is 12, should skip the name itself + 10, it is not always 0xc00c!!! Why not use dns_msg.response_position + RDLENGTH?
I believe this can cause underflow when trying to unpack the next answer, because the argument passed as the buffer size to skip_fqdn() is dns_msg->msg_size - dns_msg->answer_offset.
Can jump inside the name using compression pointers in dns_copy_qname(). Number of jumps is limited to ANCOUNT+1.
Patches
This has been fixed in:
For more information
If you have any questions or comments about this advisory:
embargo: 2020-11-18
zepsec: ZEPSEC-92
Impact
The DNS code in the Zephyr RTOS contains a possible out of bounds read which can potentially result in remote code execution.
possible read out of bounds in dns_read() in resolve.c. They unpack header id and check qr bit before they unpack the entire header.
in function dns_unpack_response_query() there is this code snippet:
what if (offset == dns_msg->msg_size)? we'll have a read out of bounds.
The following snippet of code appears in the function dns_unpack_answer() is called after skip_fqdn(). I think this check is faulty, since
msg_size
contains the actual size of the whole DNS message and it is not changed before hand as far as i've seen.Read out-of-bounds in dns_read() if RDLENGTH is bigger than the actual. Also we can uninitialized bytes in
src
:Wrong update of the answer resource record:
DNS_ANSWER_PTR_LEN is 12, should skip the name itself + 10, it is not always 0xc00c!!! Why not use dns_msg.response_position + RDLENGTH?
I believe this can cause underflow when trying to unpack the next answer, because the argument passed as the buffer size to skip_fqdn() is dns_msg->msg_size - dns_msg->answer_offset.
Can jump inside the name using compression pointers in dns_copy_qname(). Number of jumps is limited to ANCOUNT+1.
Patches
This has been fixed in:
For more information
If you have any questions or comments about this advisory:
embargo: 2020-11-18
zepsec: ZEPSEC-92