|
|
Message-ID: <7108492d-0757-96f5-f31d-a1300ec2a314@vulndisco.cc>
Date: Tue, 9 Aug 2022 15:03:34 +0300
From: Evgeny Legerov <admin@...ndisco.cc>
To: oss-security@...ts.openwall.com
Subject: Exim 4.96 overflow
Hi,
Yet another interesting issue in Exim 4.96, it is OpenBSD specific.
Combination OpenBSD + Exim is very rare, so it probably affects only two
boxes in the world,one of them is my vm.
OpenBSD dn_expand() source:
int
dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn,
char *exp_dn, int length)
{
const u_char *cp;
char *dn;
int n, c;
char *eom;
int len = -1, checked = 0;
dn = exp_dn;
cp = comp_dn;
if (length > HOST_NAME_MAX)
length = HOST_NAME_MAX;
eom = exp_dn + length;
while ((n = *cp++)) {
switch (n & INDIR_MASK) {
case 0:
if (dn != exp_dn) {
if (dn >= eom)
return (-1);
*dn++ = '.';
}
if (dn+n >= eom)
return (-1);
checked += n + 1;
while (--n >= 0) {
if (((c = *cp++) == '.') || (c == '\\')) {
if (dn + n + 2 >= eom)
return (-1);
*dn++ = '\\';
}
*dn++ = c;
if (cp >= eomorig) /* out of range */
return (-1);
}
break;
case INDIR_MASK:
if (len < 0)
len = cp - comp_dn + 1;
cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
if (cp < msg || cp >= eomorig) /* out of range */
return (-1);
checked += 2;
/*
* Check for loops in the compressed name;
* if we've looked at the whole message,
* there must be a loop.
*/
if (checked >= eomorig - msg)
return (-1);
break;
default:
return (-1); /* flag error */
}
}
*dn = '\0';
if (len < 0)
len = cp - comp_dn;
return (len);
}
As we can see, dn_expand() does not escape special characters, in
particular it ignores '\n'.
In case of Exim, after it does a reverse dns lookup, the answer is
parsed using dn_expand() and
it is stored in 'sender_host_name' global variable.
This variable is written into spool header file.
Many interesting things can happen when we control the contents of spool
file:
if (flags & 0x01) /* one_time data exists */
{
int len;
while (isdigit(*(--p)) || *p == ',' || *p == '-');
(void)sscanf(CS p+1, "%d,%d", &len, &pno);
*p = 0;
if (len > 0)
{
p -= len;
[1] errors_to = string_copy_taint(p, GET_TAINTED);
}
}
[2] *--p = 0; /* Terminate address */
As long as we control 'len' variable, we have out of bounds read on line
#1, and out of bounds write on line #2.
It may not be very practical attack,as someone says you need arp
spoofing for this attack to work.
Your opinions would be very interesting.
regards,
-e
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.