Ошибка между imapd И mail.local

2000-08-15T00:00:00
ID SECURITYVULNS:DOC:543
Type securityvulns
Reporter Securityvulns
Modified 2000-08-15T00:00:00

Description

Hello,

Надеюсь, что хотя бы из чувства патриотизма может быть еще кто-нибудь в дальнейшем решится писать в этот список рассылки до (или хотя бы одновременно) публикации в Bugtraq :)

Ошибка несерьезная, но достаточно интересная. Дело в том, что в данном случае ни одна из программ не содержит явной ошибки, тем не менее достаточно неприятные вещи вылазят из-за того, что не поддерживается единого формата почтового ящика unix. Поскольку точка зрения mail.local мне кажется более правильной, я решил отнести проблему к ошибкам imapd.

-=-=-=-=-=-=-

Заголовок : ошибки формата почтового ящика Серьезность: маленькая/средняя Угроза : недобросовестный пользователь может послать "фальшивое" письмо, таким образом обойдя защиту от вирусов, переполнений буфера и т.д в MTA/MDA или провести атаку на отказ в обслуживании на MUA или сам imap (imapd/ipopd). Затронутое программное (WU) imapd-4.7c и более ранние версии совместно обеспечение: с mail.local OC : *BSD, возможно другие Обнаружено : agk@sandy.ru, 3APA3A@security.nnov.ru Спасибо : w00w00, USSR labs

Разработчики imapd (MRC@CAC.Washington.EDU) и mail.local (Sendmail) уведомлены, но удовлетворительных вариантов решения проблемы не предложено.

Детали:

При доставке письма в Unix mailbox mail.local считает, что разделителем между письмами является пустая строка со следующим за ней заголовком "From ". Если в письме встречается такое сочетание, то "From" комментируется знаком '>'. К сожалению, imapd считает разделителем строку "From " в определенном формате, не проверяя наличия пустой строки. Это позволяет подменить заголовок "From " внутри письма, так, чтобы дальнейший текст считался относящимся к новому письму (включая полный RFC 822 заголовок).

Недобросовестный пользователь может использовать данную ошибку в двух целях: 1. Посылать письма в обход правил проверки с подмененными заголовками (в т.ч. и Received:). 2. Использовать данный факт для атаки на отказ, эмулируя огромное число писем в почтовом ящике.

Эксплоит:

perl -e 'print "1\nFrom user Wed Dec 2 05:53:22 1992\n\n"x70000' |\ mail -s "Oooops I did it again" victim

Посылает одно письмо размером примерно 3,5 Мб. Тем не менее imapd будет считать, что в ящике находится 100000 писем. При получении такого числа сообщений большая часть MUА "умирает" из-за ошибок памяти. После чего на FreeBSD 3.2, PIII, 128Мб наблюдается ситуация: imapd/ipopd "подвисают" по крайней мере на полчаса (дольше просто не тестировали) с 99% загрузкой процессора и большим потреблением памяти.

Патч (imapd-4.7c), на полноту не претендует, но конкретную дырку затыкает:

unix.c.old Wed Feb 23 03:43:30 2000 --- unix.c Thu Aug 10 12:58:19 2000
** 1048,1053 *
--- 1048,1054 ----
unsigned long i,j,k,m;
char c,
s,t,u,tmp[MAILTMPLEN],date[30];
int ti = 0,pseudoseen = NIL,retain = T;
+ int wasempty;
unsigned long nmsgs = stream->nmsgs;
unsigned long prevuid = nmsgs ? mail_elt (stream,nmsgs)->private.uid : 0; unsigned long recent = stream->recent;
***
1389,1404
k = m = 0; /
no previous line size yet
/
/
note current position
/
j = LOCAL->filesize + GETPOS (&bs);
if (i) do { / look for next message /
s = unix_mbxline (stream,&bs,&i);
if (i) { / got new data? /
! VALID (s,t,ti,zn); / yes, parse line /
if (!ti) { / not a header line, add it to message /
elt->rfc822_size +=
k = i + (m = (((i < 2) || s[i - 2] != '\r') ? 1 : 0));
/ update current position /
j = LOCAL->filesize + GETPOS (&bs);
}
}
} while (i && !ti); / until found a header /
elt->private.msg.text.text.size = j -
--- 1390,1408 ----
k = m = 0; / no previous line size yet /
/ note current position /
j = LOCAL->filesize + GETPOS (&bs);
+ wasempty = 1;
if (i) do { / look for next message /
s = unix_mbxline (stream,&bs,&i);
if (i) { / got new data? /
! if (wasempty) VALID (s,t,ti,zn); / yes, parse line /
if (!ti) { / not a header line, add it to message /
elt->rfc822_size +=
k = i + (m = (((i < 2) || s[i - 2] != '\r') ? 1 : 0));
/ update current position /
j = LOCAL->filesize + GETPOS (&bs);
}
+ if ( s == '\n') wasempty = 1;
+ else wasempty = 0;
}
} while (i && !ti); /
until found a header */
elt->private.msg.text.text.size = j -

http://www.security.nnov.ru /\_/\ { . . } |\ +--oQQo->{ ^ }<-----+ \ | 3APA3A U 3APA3A } +-------------o66o--+ / |/ You know my name - look up my number (The Beatles)