exim: apply hotfix for some ZDI reported vulnerabilities
Apply preliminary hotfix for some (three?) of the 0-day vulnerabilities reported by ZDI. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
b3a2a8b240
commit
db85d9ead6
|
@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=exim
|
PKG_NAME:=exim
|
||||||
PKG_VERSION:=4.96
|
PKG_VERSION:=4.96
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
PKG_SOURCE_URL:=https://ftp.exim.org/pub/exim/exim4/
|
PKG_SOURCE_URL:=https://ftp.exim.org/pub/exim/exim4/
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
From florz@florz.de Sun Oct 1 10:33:31 2023
|
||||||
|
Received: from [10.0.0.9] (helo=cumin.exim.org)
|
||||||
|
by mailman with esmtp (Exim 4.94.2)
|
||||||
|
(envelope-from <florz@florz.de>)
|
||||||
|
id 1qmspP-003gpc-28
|
||||||
|
for exim-dev@lists.exim.org; Sun, 01 Oct 2023 09:33:31 +0000
|
||||||
|
Authentication-Results: exim.org;
|
||||||
|
iprev=pass (rain.florz.de) smtp.remote-ip=2a07:12c0:1c00:40::1;
|
||||||
|
dmarc=none header.from=florz.de;
|
||||||
|
arc=none
|
||||||
|
Received: from rain.florz.de ([2a07:12c0:1c00:40::1]:36467)
|
||||||
|
by cumin.exim.org with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384
|
||||||
|
(Exim 4.94.2-31-503e55a2c)
|
||||||
|
(envelope-from <florz@florz.de>)
|
||||||
|
id 1qmspN-00EIpR-5w
|
||||||
|
for exim-dev@lists.exim.org; Sun, 01 Oct 2023 09:33:30 +0000
|
||||||
|
Received: from [2a07:12c0:1c00:43::121] (port=60772 helo=florz.florz.de)
|
||||||
|
by rain.florz.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256)
|
||||||
|
(Exim 4.92)
|
||||||
|
(envelope-from <florz@florz.de>)
|
||||||
|
id 1qmspL-0007Zj-F8
|
||||||
|
for exim-dev@lists.exim.org; Sun, 01 Oct 2023 11:33:27 +0200
|
||||||
|
Received: from florz by florz.florz.de with local (Exim 4.92)
|
||||||
|
(envelope-from <florz@florz.de>)
|
||||||
|
id 1qmspK-0001ZU-Sl
|
||||||
|
for exim-dev@lists.exim.org; Sun, 01 Oct 2023 11:33:26 +0200
|
||||||
|
Date: Sun, 1 Oct 2023 11:33:26 +0200
|
||||||
|
From: Florian Zumbiehl <florz@florz.de>
|
||||||
|
To: exim-dev@lists.exim.org
|
||||||
|
Message-ID: <20231001093326.GS3837@florz.florz.de>
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=us-ascii
|
||||||
|
Content-Disposition: inline
|
||||||
|
User-Agent: Mutt/1.10.1 (2018-07-13)
|
||||||
|
X-Spam-Score: 0.0 (/)
|
||||||
|
Message-ID-Hash: D3TCMSGJTLM76H6APEQXZEYOLYJKKCNZ
|
||||||
|
X-Message-ID-Hash: D3TCMSGJTLM76H6APEQXZEYOLYJKKCNZ
|
||||||
|
X-MailFrom: florz@florz.de
|
||||||
|
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-exim-dev.lists.exim.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
|
||||||
|
X-Mailman-Version: 3.3.3
|
||||||
|
Precedence: list
|
||||||
|
Subject: [exim-dev] Hotfix for some of the ZDI vulnerabilities
|
||||||
|
List-Id: Exim MTA development list <exim-dev.lists.exim.org>
|
||||||
|
List-Help: <mailto:exim-dev-request@lists.exim.org?subject=help>
|
||||||
|
List-Owner: <mailto:exim-dev-owner@lists.exim.org>
|
||||||
|
List-Post: <mailto:exim-dev@lists.exim.org>
|
||||||
|
List-Subscribe: <mailto:exim-dev-join@lists.exim.org>
|
||||||
|
List-Unsubscribe: <mailto:exim-dev-leave@lists.exim.org>
|
||||||
|
Message: 1
|
||||||
|
Status: RO
|
||||||
|
Content-Length: 5347
|
||||||
|
|
||||||
|
Hi,
|
||||||
|
|
||||||
|
below you find a patch that fixes some (probably three?) of what I guess are
|
||||||
|
the vulnerabilities reported by ZDI.
|
||||||
|
|
||||||
|
Please note that the patch is only mildly tested, it is developed based on
|
||||||
|
the git master branch, but can be applied to older versions with minor
|
||||||
|
massaging. If you go back far enough, proxy.c was part of smtp_in.c, but if
|
||||||
|
you adjust for that, the patch can be made to apply there, too.
|
||||||
|
|
||||||
|
Obviously, I have no idea whether this actually addresses what ZDI has
|
||||||
|
reported, but if not, these probably should be fixed, too, and if so, given
|
||||||
|
the fact that I managed to rather easily find these vulnerabilities based
|
||||||
|
on the information that's publicly available, I don't think there is much
|
||||||
|
point to trying to keep this secret any longer--if anything, it's
|
||||||
|
counterproductive.
|
||||||
|
|
||||||
|
Also mind you that this is a hot fix, it's neither elegant, nor does it do
|
||||||
|
any useful error reporting, the goal was simply to prevent out of bounds
|
||||||
|
accesses.
|
||||||
|
|
||||||
|
Florian
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/src/auths/external.c
|
||||||
|
+++ b/src/auths/external.c
|
||||||
|
@@ -100,6 +100,9 @@ if (expand_nmax == 0) /* skip if rxd da
|
||||||
|
if ((rc = auth_prompt(CUS"")) != OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
+if (expand_nmax != 1)
|
||||||
|
+ return FAIL;
|
||||||
|
+
|
||||||
|
if (ob->server_param2)
|
||||||
|
{
|
||||||
|
uschar * s = expand_string(ob->server_param2);
|
||||||
|
--- a/src/auths/spa.c
|
||||||
|
+++ b/src/auths/spa.c
|
||||||
|
@@ -165,12 +165,18 @@ if (auth_get_no64_data(&data, msgbuf) !=
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
/* dump client response */
|
||||||
|
-if (spa_base64_to_bits(CS &response, sizeof(response), CCS data) < 0)
|
||||||
|
+int l = spa_base64_to_bits(CS &response, sizeof(response), CCS data);
|
||||||
|
+if (l < 0)
|
||||||
|
{
|
||||||
|
DEBUG(D_auth) debug_printf("auth_spa_server(): bad base64 data in "
|
||||||
|
"response: %s\n", data);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
+if(l < (char *)&response.buffer - (char *)&response)return FAIL;
|
||||||
|
+unsigned long o = IVAL(&response.uUser.offset, 0);
|
||||||
|
+if((l < o) || (l - o < SVAL(&response.uUser.len, 0)))return FAIL;
|
||||||
|
+o = IVAL(&response.ntResponse.offset, 0);
|
||||||
|
+if((l < o) || (l - o < 24))return FAIL;
|
||||||
|
|
||||||
|
/***************************************************************
|
||||||
|
PH 07-Aug-2003: The original code here was this:
|
||||||
|
@@ -345,7 +351,10 @@ if (!smtp_read_response(sx, US buffer, b
|
||||||
|
|
||||||
|
/* convert the challenge into the challenge struct */
|
||||||
|
DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4);
|
||||||
|
-spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4));
|
||||||
|
+int l = spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4));
|
||||||
|
+if((l < 0) || (l < (char *)&challenge.buffer - (char *)&challenge))return FAIL;
|
||||||
|
+unsigned long o = IVAL(&challenge.uDomain.offset, 0);
|
||||||
|
+if((l < o) || (l - o < SVAL(&challenge.uDomain.len, 0)))return FAIL;
|
||||||
|
|
||||||
|
spa_build_auth_response(&challenge, &response, CS username, CS password);
|
||||||
|
spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response));
|
||||||
|
--- a/src/smtp_in.c
|
||||||
|
+++ b/src/smtp_in.c
|
||||||
|
@@ -1172,6 +1172,8 @@ while (capacity > 0)
|
||||||
|
do { ret = read(fd, to, 1); } while (ret == -1 && errno == EINTR && !had_command_timeout);
|
||||||
|
if (ret == -1)
|
||||||
|
return -1;
|
||||||
|
+ if (!ret)
|
||||||
|
+ break;
|
||||||
|
have++;
|
||||||
|
if (last)
|
||||||
|
return have;
|
||||||
|
@@ -1320,6 +1322,8 @@ if ((ret == PROXY_INITIAL_READ) && (memc
|
||||||
|
goto proxyfail;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (ret < 16)
|
||||||
|
+ goto proxyfail;
|
||||||
|
/* The v2 header will always be 16 bytes per the spec. */
|
||||||
|
size = 16 + ntohs(hdr.v2.len);
|
||||||
|
DEBUG(D_receive) debug_printf("Detected PROXYv2 header, size %d (limit %d)\n",
|
||||||
|
@@ -1340,7 +1344,7 @@ if ((ret == PROXY_INITIAL_READ) && (memc
|
||||||
|
{
|
||||||
|
retmore = read(fd, (uschar*)&hdr + ret, size-ret);
|
||||||
|
} while (retmore == -1 && errno == EINTR && !had_command_timeout);
|
||||||
|
- if (retmore == -1)
|
||||||
|
+ if (retmore < 1)
|
||||||
|
goto proxyfail;
|
||||||
|
ret += retmore;
|
||||||
|
DEBUG(D_receive) debug_printf("PROXYv2: have %d/%d required octets\n", ret, size);
|
||||||
|
@@ -1362,6 +1366,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig,
|
||||||
|
switch (hdr.v2.fam)
|
||||||
|
{
|
||||||
|
case 0x11: /* TCPv4 address type */
|
||||||
|
+ if (ret < 28)
|
||||||
|
+ goto proxyfail;
|
||||||
|
iptype = US"IPv4";
|
||||||
|
tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr;
|
||||||
|
inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip));
|
||||||
|
@@ -1388,6 +1394,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig,
|
||||||
|
proxy_external_port = tmpport;
|
||||||
|
goto done;
|
||||||
|
case 0x21: /* TCPv6 address type */
|
||||||
|
+ if (ret < 52)
|
||||||
|
+ goto proxyfail;
|
||||||
|
iptype = US"IPv6";
|
||||||
|
memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16);
|
||||||
|
inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6));
|
||||||
|
@@ -1446,10 +1454,13 @@ else if (ret >= 8 && memcmp(hdr.v1.line,
|
||||||
|
goto proxyfail;
|
||||||
|
ret += r2;
|
||||||
|
|
||||||
|
+ if(ret > 107)
|
||||||
|
+ goto proxyfail;
|
||||||
|
+ hdr.v1.line[ret] = 0;
|
||||||
|
p = string_copy(hdr.v1.line);
|
||||||
|
end = memchr(p, '\r', ret - 1);
|
||||||
|
|
||||||
|
- if (!end || (end == (uschar*)&hdr + ret) || end[1] != '\n')
|
||||||
|
+ if (!end || end[1] != '\n')
|
||||||
|
{
|
||||||
|
DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n");
|
||||||
|
goto proxyfail;
|
Loading…
Reference in New Issue