Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:543
HistoryAug 15, 2000 - 12:00 a.m.

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

2000-08-1500:00:00
vulners.com
42

Hello,

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

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

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

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

Разработчики imapd ([email protected]) и 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 &#40;i&#41; do {             /* look for next message */                  
        s = unix_mbxline &#40;stream,&amp;bs,&amp;i&#41;;                                  
        if &#40;i&#41; {              /* 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 &#40; *s == &#39;&#92;n&#39;&#41; wasempty = 1;                                   
    
  •       else wasempty = 0;                                               
        }                                                                  
      } while &#40;i &amp;&amp; !ti&#41;;     /* until found a header */                   
      elt-&gt;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)