|
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.