Läsa nästa text.
5034514 2000-04-24 23:20 /101 rader/ Postmaster
Mottagare: Bugtraq (import) <10602>
Ärende: unsafe fgets() in sendmail's mail.local
------------------------------------------------------------
Approved-By: aleph1@SECURITYFOCUS.COM
Delivered-To: bugtraq@lists.securityfocus.com
Delivered-To: bugtraq@securityfocus.com
X-Priority: 3 (Normal)
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-ID: <2694.000424@SECURITY.NNOV.RU>
Date: Mon, 24 Apr 2000 16:40:32 +0400
Reply-To: 3APA3A <3APA3A@SECURITY.NNOV.RU>
Sender: Bugtraq List <BUGTRAQ@SECURITYFOCUS.COM>
From: 3APA3A <3APA3A@SECURITY.NNOV.RU>
Organization: http://www.security.nnov.ru
X-To: bugtraq@security.nnov.ru, bugtraq@securityfocus.com
X-cc: security-officer@freebsd.org
To: BUGTRAQ@SECURITYFOCUS.COM
Topic:
unsafe fgets() in sendmail's mail.local
Description:
There are 4 problems:
1. Possibility to insert LMTP commands into e-mail message
2. Possibility of deadlock between sendmail and mail.local
3. Possibility to corrupt user's mailbox
4. Possibility to change e-mail headers of the message in user's
mailbox
Vulnerable software:
Problems 1 and 2: sendmail before 8.10.0 (8.9.3 tested), all
platforms
Problems 3 and 4: sendmail 8.10.0 and 8.10.1 (8.10.1 tested)
under Solaris only
Status: vendor contacted, problems 1 and 2 are patched in sendmail 8.10.0
Long description:
Problem 1:
While in LMTP mode mail.local checks input for ".\n" string to find
the end of the message. Sendmail will not allow this string to pass
through, but using of fgets() with buffersize 2048 allows to emulate
end of the message with a string
"(2047 chars).\n"
The rest of the message will be treated as LMTP commands. This allows
to send messages to multiple mailboxes (including private and closed
ones) with any spoofed information bypassing sendmail and without any
filtering, checking, logging etc.
Problem 2:
In the conditions of the problem 1, mail.local will return LMTP
answers to sendmail. Because sendmail doesn't expects any output from
mail.local at this point, replies will not be taken from I/O buffer.
If extreamaly large number of LMTP commands is used in the text, or
the rest of the message is just a collection of text strings (in this
case mail.local will reply with a error for every string) sendmail
and mail.local will be deadlocked then the buffer will be filled.
This deadlock problem regardless to LMTP command execution was
reported to sendmail team by Peter Jeremy and patched in 8.10.0
release.
Problem 3:
sendmail 8.10.0 introduces support for "Content-Length: " header for
Solaris in mail.local. This header stores the size of the message and
is used by mail retrieving software (f.e. qpopper) to calculate
message boundary in the mailbox. If this header already exists in
message it will be stripped, but because fgets() is used for parsing
message it's possible to add "Content-Length: 99999999" header and
comment out real "Content-Length: " causing mailbox corruption using
strings
"(2047 chars)\n"
"Content-Length: 99999999\n"
in the end of message header.
Problem 4:
If message body is empty and last string of the message header is
"(2047 chars)Content-Length: \n"
the headers of this message will be glued to the next message in
mailbox, because '\n' character will be lost while stripping
Content-Length.
http://www.security.nnov.ru
/\_/\
{ . . } |\
+--oQQo->{ ^ }<-----+ \
| 3APA3A U 3APA3A }
+-------------o66o--+ /
|/
You know my name - look up my number (The Beatles)
(5034514) ------------------------------------------
5038233 2000-04-26 05:27 /149 rader/ Postmaster
Mottagare: Bugtraq (import) <10620>
Ärende: Re: unsafe fgets() in sendmail's mail.local
------------------------------------------------------------
Approved-By: aleph1@SECURITYFOCUS.COM
Delivered-To: bugtraq@lists.securityfocus.com
Delivered-To: BUGTRAQ@SECURITYFOCUS.COM
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="vkogqOf2sHV7VnPd"
Message-ID: <20000425091054.A30214@zardoc.endmail.org>
Date: Tue, 25 Apr 2000 09:10:54 -0700
Reply-To: Claus Assmann <ca+bugtraq@ZARDOC.ENDMAIL.ORG>
Sender: Bugtraq List <BUGTRAQ@SECURITYFOCUS.COM>
From: Claus Assmann <ca+bugtraq@ZARDOC.ENDMAIL.ORG>
X-To: BUGTRAQ@SECURITYFOCUS.COM
To: BUGTRAQ@SECURITYFOCUS.COM
In-Reply-To: <2694.000424@SECURITY.NNOV.RU>; from 3APA3A@SECURITY.NNOV.RU o
Mon, Apr 24, 2000 at 04:40:32PM +0400
--vkogqOf2sHV7VnPd
Content-Type: text/plain; charset=us-ascii
On Mon, Apr 24, 2000, 3APA3A wrote:
> Topic:
> unsafe fgets() in sendmail's mail.local
> 1. Possibility to insert LMTP commands into e-mail message
> 2. Possibility of deadlock between sendmail and mail.local
> 3. Possibility to corrupt user's mailbox
> 4. Possibility to change e-mail headers of the message in user's
> mailbox
> Vulnerable software:
> Problems 1 and 2: sendmail before 8.10.0 (8.9.3 tested), all
> platforms
> Problems 3 and 4: sendmail 8.10.0 and 8.10.1 (8.10.1 tested)
> under Solaris only
Thanks for the notification and your help to create a patch.
The attached patch will be in the next release of sendmail.
PS: Content-Length: shouldn't be used anyway :-)
--vkogqOf2sHV7VnPd
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="p.m.c"
Index: mail.local.c
===================================================================
RCS file: /cvs/mail.local/mail.local.c,v
retrieving revision 8.145
retrieving revision 8.146
diff -u -r8.145 -r8.146
--- mail.local.c 2000/04/25 15:27:08 8.145
+++ mail.local.c 2000/04/25 15:48:32 8.146
@@ -746,7 +746,8 @@
FILE *fp = NULL;
time_t tval;
bool eline;
- bool fullline = TRUE;
+ bool fullline = TRUE; /* current line is terminated */
+ bool prevfl; /* previous line was terminated */
char line[2048];
int fd;
char tmpbuf[sizeof _PATH_LOCTMP + 1];
@@ -783,16 +784,19 @@
#endif /* CONTENTLENGTH */
line[0] = '\0';
- for (eline = TRUE; fgets(line, sizeof(line), stdin); )
+ eline = TRUE;
+ while (fgets(line, sizeof(line), stdin) != (char *)NULL)
{
size_t line_len = 0;
int peek;
+
+ prevfl = fullline; /* preserve state of previous line */
while (line[line_len] != '\n' && line_len < sizeof(line) - 2)
line_len++;
line_len++;
/* Check for dot-stuffing */
- if (fullline && lmtprcpts && line[0] == '.')
+ if (prevfl && lmtprcpts && line[0] == '.')
{
if (line[1] == '\n' ||
(line[1] == '\r' && line[2] == '\n'))
@@ -801,7 +805,7 @@
line_len--;
}
- /* Check to see if we have the full line from the fgets() */
+ /* Check to see if we have the full line from fgets() */
fullline = FALSE;
if (line_len > 0)
{
@@ -809,12 +813,11 @@
{
if (line_len >= 2 &&
line[line_len - 2] == '\r')
- {
- (void) strlcpy(line + line_len - 2,
- "\n", sizeof line -
- line_len + 2);
+ {
+ line[line_len - 2] = '\n';
+ line[line_len - 1] = '\0';
line_len--;
- }
+ }
fullline = TRUE;
}
else if (line[line_len - 1] == '\r')
@@ -834,7 +837,7 @@
fullline = TRUE;
#ifdef CONTENTLENGTH
- if (line[0] == '\n' && HeaderLength == 0)
+ if (prevfl && line[0] == '\n' && HeaderLength == 0)
{
eline = FALSE;
HeaderLength = ftell(fp);
@@ -849,7 +852,7 @@
}
}
#else /* CONTENTLENGTH */
- if (line[0] == '\n')
+ if (prevfl && line[0] == '\n')
eline = TRUE;
#endif /* CONTENTLENGTH */
else
@@ -860,10 +863,17 @@
eline = FALSE;
#ifdef CONTENTLENGTH
/* discard existing "Content-Length:" headers */
- if (HeaderLength == 0 &&
+ if (prevfl && HeaderLength == 0 &&
(line[0] == 'C' || line[0] == 'c') &&
strncasecmp(line, ContentHdr, 15) == 0)
- continue;
+ {
+ /*
+ ** be paranoid: clear the line
+ ** so no "wrong matches" may occur later
+ */
+ line[0] = '\0';
+ continue;
+ }
#endif /* CONTENTLENGTH */
}
--vkogqOf2sHV7VnPd--
(5038233) ------------------------------------------