端口掃描之開放端口掃描方式

端口掃描器

參考:https://www.imooc.com/article/286803

常見的端口掃描類型

1. TCP 連接掃描
2. TCP SYN 掃描(也稱爲半開放掃描或stealth掃描)
3. TCP 聖誕樹(Xmas Tree)掃描
4. TCP FIN 掃描
5. TCP 空掃描(Null)
6. TCP ACK 掃描
7. TCP 窗口掃描
8. UDP 掃描

1、TCP連接掃描

若客戶端想要連接服務器80端口時,會先發送一個帶有 SYN 標識和端口號的 TCP 數據包給服務器(本例中爲80端口)。如果端口是開放的,則服務器會接受這個連接並返回一個帶有 SYN 和 ACK 標識的數據包給客戶端。隨後客戶端會返回帶有 ACK 和 RST 標識的數據包,此時客戶端與服務器建立了連接。

  • 如果完成一次三次握手,那麼服務器上對應的端口肯定就是開放的。

  • 當客戶端發送一個帶有 SYN 標識和端口號的 TCP 數據包給服務器後,如果服務器端返回一個帶 RST 標識的數據包,則說明端口處於關閉狀態

nmap的-sT模式

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

tcp_connect_scan_resp = sr1(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=10)
if(str(type(tcp_connect_scan_resp))==""):
    print( "Closed")
elif(tcp_connect_scan_resp.haslayer(TCP)):
    if(tcp_connect_scan_resp.getlayer(TCP).flags == 0x12):
        send_rst = sr(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="AR"),timeout=10)# 全連接 AR => ACK+RST
        print( "Open")
elif (tcp_connect_scan_resp.getlayer(TCP).flags == 0x14):
    print( "Closed")

2、TCP SYN 掃描

客戶端向服務器發送一個帶有 SYN 標識和端口號的數據包,這種技術主要用於躲避防火牆的檢測。

  • 如果目標端口開發,則會返回帶有 SYN 和 ACK 標識的 TCP 數據包。但是,這時客戶端不會返回 RST+ACK 而是返回一個只帶有 RST 標識的數據包。

  • 如果目標端口處於關閉狀態,那麼同之前一樣,服務器會返回一個 RST 數據包

nmap的-sS模式

#! /usr/bin/python
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

stealth_scan_resp = sr1(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=10)
if(str(type(stealth_scan_resp))==""):
    print ("Filtered")
elif(stealth_scan_resp.haslayer(TCP)):
    if(stealth_scan_resp.getlayer(TCP).flags == 0x12):
        send_rst = sr(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="R"),timeout=10)			# 連接 R==>RST
        print( "Open")
    elif (stealth_scan_resp.getlayer(TCP).flags == 0x14):
        print ("Closed")
elif(stealth_scan_resp.haslayer(ICMP)):
    if(int(stealth_scan_resp.getlayer(ICMP).type)==3 and int(stealth_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
        print ("Filtered")

3、TCP 聖誕樹(Xmas Tree)掃描

在聖誕樹掃描中,客戶端會向服務器發送帶有 PSH,FIN,URG 標識和端口號的數據包給服務器。

  • 如果目標端口是開放的,那麼不會有任何來自服務器的迴應。

  • 如果服務器返回了一個帶有 RST 標識的 TCP 數據包,那麼說明端口處於關閉狀態。

  • 如果服務器返回了一個 ICMP 數據包,其中包含 ICMP 目標不可達錯誤類型3以及 ICMP 狀態碼爲1,2,3,9,10或13,則說明目標端口被過濾了無法確定是否處於開放狀態。

nmap -sX模式

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

xmas_scan_resp = sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="FPU"),timeout=10)
if (str(type(xmas_scan_resp))==""):
    print( "Open|Filtered")
elif(xmas_scan_resp.haslayer(TCP)):
    if(xmas_scan_resp.getlayer(TCP).flags == 0x14):
        print( "Closed")
elif(xmas_scan_resp.haslayer(ICMP)):
    if(int(xmas_scan_resp.getlayer(ICMP).type)==3 and int(xmas_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
        print ("Filtered")

4、FIN掃描

FIN 掃描會向服務器發送帶有 FIN 標識和端口號的 TCP 數據包。

  • 如果沒有服務器端迴應則說明端口開放。

  • 如果服務器返回一個 RST 數據包,則說明目標端口是關閉的。

  • 如果服務器返回了一個 ICMP 數據包,其中包含 ICMP 目標不可達錯誤類型3以及 ICMP 代碼爲1,2,3,9,10或13,則說明目標端口被過濾了無法確定端口狀態。

nmap -sF模式

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

fin_scan_resp = sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="F"),timeout=10)
if (str(type(fin_scan_resp))==""):
    print ("Open|Filtered")
elif(fin_scan_resp.haslayer(TCP)):
    if(fin_scan_resp.getlayer(TCP).flags == 0x14):
        print ("Closed")
elif(fin_scan_resp.haslayer(ICMP)):
    if(int(fin_scan_resp.getlayer(ICMP).type)==3 and int(fin_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
        print ("Filtered")

5、TCP 空掃描(Null)

在空掃描中,客戶端發出的 TCP 數據包僅僅只會包含端口號而不會有其他任何的標識信息。

  • 如果目標端口是開放的則不會回覆任何信息。

  • 如果服務器返回了一個 RST 數據包,則說明目標端口是關閉的。

  • 如果返回 ICMP 錯誤類型3且代碼爲1,2,3,9,10或13的數據包,則說明端口被服務器過濾了。

nmap -sN模式

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

null_scan_resp = sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags=""),timeout=10)
if (str(type(null_scan_resp))==""):
    print( "Open|Filtered")
elif(null_scan_resp.haslayer(TCP)):
    if(null_scan_resp.getlayer(TCP).flags == 0x14):
        print ("Closed")
elif(null_scan_resp.haslayer(ICMP)):
    if(int(null_scan_resp.getlayer(ICMP).type)==3 and int(null_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
        print ("Filtered")

6、TCP ACK掃描

ACK 掃描不是用於發現端口開啓或關閉狀態的,而是用於發現服務器上是否存在有狀態防火牆的。它的結果只能說明端口是否被過濾。再次強調,ACK 掃描不能發現端口是否處於開啓或關閉狀態。

  • 客戶端會發送一個帶有 ACK 標識和端口號的數據包給服務器。如果服務器返回一個帶有 RST 標識的 TCP 數據包,則說明端口沒有被過濾,不存在狀態防火牆。

  • 如果目標服務器沒有任何迴應或者返回ICMP 錯誤類型3且代碼爲1,2,3,9,10或13的數據包,則說明端口被過濾且存在狀態防火牆。

nmap -sA模式
#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

ack_flag_scan_resp = sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="A"),timeout=10)
if (str(type(ack_flag_scan_resp))==""):
    print ("Stateful firewall presentn(Filtered)")
elif(ack_flag_scan_resp.haslayer(TCP)):
    if(ack_flag_scan_resp.getlayer(TCP).flags == 0x4):
        print ("No firewalln(Unfiltered)")
elif(ack_flag_scan_resp.haslayer(ICMP)):
    if(int(ack_flag_scan_resp.getlayer(ICMP).type)==3 and int(ack_flag_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]):
        print ("Stateful firewall presentn(Filtered)")

7、TCP窗口掃描

TCP 窗口掃描的流程同 ACK 掃描類似,同樣是客戶端向服務器發送一個帶有 ACK 標識和端口號的 TCP 數據包,但是這種掃描能夠用於發現目標服務器端口的狀態。在 ACK 掃描中返回 RST 表明沒有被過濾,但在窗口掃描中,當收到返回的 RST 數據包後,它會檢查窗口大小的值。

  • 如果窗口大小的值是個非零值,則說明目標端口是開放的。

  • 如果返回的 RST 數據包中的窗口大小爲0,則說明目標端口是關閉的。

nmap -sW模式

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=80

window_scan_resp = sr1(IP(dst=dst_ip)/TCP(dport=dst_port,flags="A"),timeout=10)
if (str(type(window_scan_resp))==""):
    print( "No response")
elif(window_scan_resp.haslayer(TCP)):
    if(window_scan_resp.getlayer(TCP).window == 0):
        print( "Closed")
    elif(window_scan_resp.getlayer(TCP).window > 0):
        print( "Open")

8、UDP掃描

TCP 是面向連接的協議,而UDP則是無連接的協議。

面向連接的協議會先在客戶端和服務器之間建立通信信道,然後纔會開始傳輸數據。如果客戶端和服務器之間沒有建立通信信道,則不會有任何產生任何通信數據。

無連接的協議則不會事先建立客戶端和服務器之間的通信信道,只要客戶端到服務器存在可用信道,就會假設目標是可達的然後向對方發送數據。

  • 客戶端會向服務器發送一個帶有端口號的 UDP 數據包。如果服務器回覆了 UDP 數據包,則目標端口是開放的。

  • 如果服務器返回了一個 ICMP 目標不可達的錯誤和代碼3,則意味着目標端口處於關閉狀態。

  • 如果服務器返回一個 ICMP 錯誤類型3且代碼爲1,2,3,9,10或13的數據包,則說明目標端口被服務器過濾了。

  • 如果服務器沒有任何相應客戶端的 UDP 請求,則可以斷定目標端口可能是開放或被過濾的,無法判斷端口的最終狀態。

#! /usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

dst_ip = "10.0.0.1"
src_port = RandShort()
dst_port=53
dst_timeout=10

def udp_scan(dst_ip,dst_port,dst_timeout):
    udp_scan_resp = sr1(IP(dst=dst_ip)/UDP(dport=dst_port),timeout=dst_timeout)
    if (str(type(udp_scan_resp))==""):
        retrans = []
        for count in range(0,3):
            retrans.append(sr1(IP(dst=dst_ip)/UDP(dport=dst_port),timeout=dst_timeout))
        for item in retrans:
            if (str(type(item))!=""):
                udp_scan(dst_ip,dst_port,dst_timeout)
        return ("Open|Filtered")
    elif (udp_scan_resp.haslayer(UDP)):
        return( "Open")
    elif(udp_scan_resp.haslayer(ICMP)):
        if(int(udp_scan_resp.getlayer(ICMP).type)==3 and int(udp_scan_resp.getlayer(ICMP).code)==3):
            return( "Closed")
        elif(int(udp_scan_resp.getlayer(ICMP).type)==3 and int(udp_scan_resp.getlayer(ICMP).code) in [1,2,9,10,13]):
            return( "Filtered")

print udp_scan(dst_ip,dst_port,dst_timeout)
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章