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)