From a3b03a908948217a6d9dbe8632032af4990dbed0 Mon Sep 17 00:00:00 2001 From: Mikhail Grigorev Date: Tue, 20 Feb 2024 00:03:21 +0500 Subject: [PATCH] [ZBX-23855] Possible buffer overread from reading DNS responses (CVE-2023-32726) --- src/libs/zbxsysinfo/common/dns.c | 67 +++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/libs/zbxsysinfo/common/dns.c b/src/libs/zbxsysinfo/common/dns.c index 394a5254..70e81822 100644 --- a/src/libs/zbxsysinfo/common/dns.c +++ b/src/libs/zbxsysinfo/common/dns.c @@ -638,7 +638,8 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans { if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, + "Cannot decode DNS response: cannot expand domain name.")); ret = SYSINFO_RET_FAIL; goto clean; } @@ -651,6 +652,13 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans GETSHORT(q_len, msg_ptr); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type)); + if (msg_ptr + q_len > msg_end) + { + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response: record overflow.")); + ret = SYSINFO_RET_FAIL; + goto clean; + } + switch (q_type) { case T_A: @@ -695,8 +703,40 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans case T_PTR: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); +#define ERR_MSG_PREFIX "Cannot decode DNS response: cannot expand " + const char *err_msg = NULL; + + switch (q_type) + { + case T_NS: + err_msg = ERR_MSG_PREFIX "name server name."; + break; + case T_CNAME: + err_msg = ERR_MSG_PREFIX "canonical name."; + break; + case T_MB: + err_msg = ERR_MSG_PREFIX "mailbox name."; + break; + case T_MD: + err_msg = ERR_MSG_PREFIX "mail destination name."; + break; + case T_MF: + err_msg = ERR_MSG_PREFIX "mail forwarder name."; + break; + case T_MG: + err_msg = ERR_MSG_PREFIX "mail group name."; + break; + case T_MR: + err_msg = ERR_MSG_PREFIX "renamed mailbox name."; + break; + case T_PTR: + err_msg = ERR_MSG_PREFIX "PTR name."; + break; + } + + SET_MSG_RESULT(result, zbx_strdup(NULL, err_msg)); return SYSINFO_RET_FAIL; +#undef ERR_MSG_PREFIX } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; @@ -706,7 +746,8 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand mail exchange name.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); @@ -715,20 +756,22 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans case T_SOA: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand source nameserver name.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand administrator mailbox name.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); GETLONG(value, msg_ptr); /* serial number */ - offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); + offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %u", (zbx_uint32_t)value); GETLONG(value, msg_ptr); /* refresh time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); @@ -750,7 +793,8 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans case T_WKS: if (INT32SZ + 1 > q_len) { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " malformed WKS resource record.")); return SYSINFO_RET_FAIL; } @@ -816,14 +860,16 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans case T_MINFO: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand mailbox responsible for mailing lists.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand mailbox for error messages.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); @@ -854,7 +900,8 @@ static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */ { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:" + " cannot expand service target hostname.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);