oss-sec mailing list archives
Exim 4.96 overflow
From: Evgeny Legerov <admin () vulndisco cc>
Date: Tue, 9 Aug 2022 15:03:34 +0300
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
Current thread:
- Exim 4.96 overflow Evgeny Legerov (Aug 09)
