exim: update to version 4.96.1

This is a security release.

JH/01 Bug 2999: Fix a possible OOB write in the external authenticator, which
      could be triggered by externally-supplied input.  Found by Trend Micro.
      CVE-2023-42115

JH/02 Bug 3000: Fix a possible OOB write in the SPA authenticator, which could
      be triggered by externally-controlled input.  Found by Trend Micro.
      CVE-2023-42116

JH/03 Bug 3001: Fix a possible OOB read in the SPA authenticator, which could
      be triggered by externally-controlled input.  Found by Trend Micro.
      CVE-2023-42114

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2023-10-06 23:38:23 +02:00
parent 36566a99af
commit 7c8f4a2a1c
2 changed files with 3 additions and 188 deletions

View File

@ -1,12 +1,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=exim
PKG_VERSION:=4.96
PKG_RELEASE:=2
PKG_VERSION:=4.96.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://ftp.exim.org/pub/exim/exim4/
PKG_HASH:=299a56927b2eb3477daafd3c5bda02bc67e5c4e5898a7aeaf2740875278cf1a3
PKG_HASH:=93ac0755c317e1fdbbea8ccb70a868876bdf3148692891c72ad0fe816767033d
PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
PKG_LICENSE:=GPL-2.0-or-later

View File

@ -1,185 +0,0 @@
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;