返回文章列表

Python-nmap 網路掃描技術應用

本文探討如何使用 Python-nmap 進行網路掃描,包含同步和非同步掃描模式,並解析掃描結果。同時示範如何利用 Nmap 指令碼引擎 (NSE) 進行服務和漏洞發現,以及如何使用 os 和 subprocess 模組直接執行 Nmap 指令,提供更全面的網路掃描解決方案。

網路安全 Web 開發

Python-nmap 提供了便捷的網路掃描功能,讓開發者能以 Python 程式控制 Nmap 進行主機探測。同步掃描模式適合單一目標,程式會逐一完成每個掃描任務。而非同步掃描模式則允許多個掃描任務平行,有效提升掃描效率,適用於大規模網路掃描。除了使用 python-nmap 函式庫,開發者也可以透過 os 和 subprocess 模組直接執行 Nmap 指令,彈性運用 Nmap 的各種功能。更進一步,Nmap 指令碼引擎 (NSE) 提供豐富的指令碼,可針對特定服務和漏洞進行深入探測,提升網路安全分析能力。

非同步掃描實作

在下面的範例中,我們將展示如何使用 python-nmap 實作非同步掃描。

#!/usr/bin/env python3
import nmap
import threading

class NmapScannerAsync:
    def __init__(self):
        self.portScanner = nmap.PortScanner()

    def nmapScanAsync(self, ip_address, port):
        thread = threading.Thread(target=self.nmapScan, args=(ip_address, port))
        thread.start()

    def nmapScan(self, ip_address, port):
        self.portScanner.scan(ip_address, port)
        self.state = self.portScanner[ip_address]['tcp'][int(port)]['state']
        print(" [+] Executing command: ", self.portScanner.command_line())
        print(" [+] "+ ip_address + " tcp/" + port + " " + self.state)

def main():
    ip_address = '45.33.32.156'
    ports = ['21', '22', '23', '25', '80']
    scanner = NmapScannerAsync()
    for port in ports:
        scanner.nmapScanAsync(ip_address, port)

if __name__ == "__main__":
    main()

內容解密:

  1. NmapScannerAsync 類別:這個類別提供了非同步掃描的功能。
  2. nmapScanAsync 方法:為每個埠建立一個新的執行緒,並在該執行緒中呼叫 nmapScan 方法進行掃描。
  3. nmapScan 方法:與同步掃描中的 nmapScan 方法類別似,但現在是在單獨的執行緒中執行。

非同步掃描的優點

  • 提高效率:非同步掃描允許同時掃描多個埠,大大提高了掃描效率。
  • 靈活性:可以根據需要定義回呼函式,對掃描結果進行進一步處理。

使用python-nmap進行掃描模式分析

python-nmap是一個強大的Python函式庫,用於與Nmap掃描器進行互動,實作網路掃描和主機檢測。本文將探討如何使用python-nmap進行同步和非同步掃描,並解析掃描結果。

同步掃描模式

同步掃描是指一次執行一個掃描任務,直到完成後才開始下一個任務。以下是一個使用python-nmap進行同步掃描的範例:

import nmap

# 建立PortScanner物件
portScanner = nmap.PortScanner()

# 掃描特定主機的特定埠
open_ports_dict = portScanner.scan('45.33.32.156', arguments="-O -v")

# 解析掃描結果
if open_ports_dict is not None:
    open_ports_dict = open_ports_dict.get("scan").get('45.33.32.156').get("tcp")
    print("開放埠描述")
    port_list = open_ports_dict.keys()
    for port in port_list:
        print(port, "
---
\t-->", open_ports_dict.get(port)['name'])

    print("\n
---
-
---
-
---
---
作業系統詳細資訊
---
-
---
-
---
-
---
-
---
--\n")
    print("被掃描主機的詳細資訊:\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['cpe'])
    print("作業系統家族是:\t\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['osfamily'])
    print("作業系統型別是:\t\t\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['type'])
    print("作業系統版本是:\t\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['osgen'])
    print("作業系統供應商是:\t\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['vendor'])
    print("偵測準確度是:\t\t", portScanner['45.33.32.156']['osmatch'][0]['osclass'][0]['accuracy'])

內容解密:

  1. 建立PortScanner物件:使用nmap.PortScanner()建立一個PortScanner物件,用於執行Nmap掃描。
  2. 掃描特定主機的特定埠:呼叫portScanner.scan()方法,傳入目標主機IP和掃描引數(此例中為-O -v,用於偵測作業系統和詳細輸出)。
  3. 解析掃描結果:從scan()方法的回傳值中提取TCP埠資訊和作業系統資訊,並進行列印輸出。
  4. 輸出開放埠和作業系統資訊:遍歷開放的TCP埠,列印埠號和對應的服務名稱。同時,輸出偵測到的作業系統詳細資訊,包括作業系統家族、型別、版本、供應商和偵測準確度。

非同步掃描模式

非同步掃描允許多個掃描任務平行執行,提高了掃描效率。以下是一個使用python-nmap進行非同步掃描的範例:

import nmap

# 建立PortScannerAsync物件
portScannerAsync = nmap.PortScannerAsync()

# 定義回呼函式
def callback_result(host, scan_result):
    print(host, scan_result)

# 執行非同步掃描
portScannerAsync.scan(hosts='scanme.nmap.org', arguments='-p 21', callback=callback_result)
portScannerAsync.scan(hosts='scanme.nmap.org', arguments='-p 22', callback=callback_result)
portScannerAsync.scan(hosts='scanme.nmap.org', arguments='-p 23', callback=callback_result)
portScannerAsync.scan(hosts='scanme.nmap.org', arguments='-p 80', callback=callback_result)

# 等待掃描完成
while portScannerAsync.still_scanning():
    print("掃描中 >>>")
    portScannerAsync.wait(5)

內容解密:

  1. 建立PortScannerAsync物件:使用nmap.PortScannerAsync()建立一個PortScannerAsync物件,用於執行非同步Nmap掃描。
  2. 定義回呼函式:定義一個callback_result()函式,用於在每次掃描完成時被呼叫,列印掃描結果。
  3. 執行非同步掃描:呼叫portScannerAsync.scan()方法,傳入目標主機、掃描引數和回呼函式,執行非同步掃描。
  4. 等待掃描完成:使用while迴圈和still_scanning()方法等待所有掃描任務完成,並定期列印掃描進度。

重點解析

  • 同步與非同步掃描:python-nmap支援同步和非同步兩種掃描模式。同步掃描適用於簡單的掃描任務,而非同步掃描則能提高複雜掃描任務的效率。
  • 掃描結果解析:無論是同步還是非同步掃描,python-nmap都提供了豐富的API來解析掃描結果,包括開放埠資訊和作業系統詳細資訊。
  • 許可權需求:某些Nmap掃描功能(如作業系統偵測)需要root許可權,因此在執行相關指令碼時可能需要使用sudo

使用 Python-nmap 進行非同步掃描與 Nmap 指令執行

在前面的章節中,我們已經瞭解如何使用 python-nmap 進行基本的連線埠掃描。在本章節中,我們將進一步探討如何使用 python-nmap 進行非同步掃描,以及如何利用 os 和 subprocess 模組執行 Nmap 指令。

非同步掃描的實作

非同步掃描允許我們在掃描多個連線埠時,不必等待前一個掃描完成即可開始下一個掃描。這種方式可以大幅提高掃描的效率。以下是一個使用 python-nmap 進行非同步掃描的範例:

#!/usr/bin/env python3
import nmap
import argparse

def callbackResult(host, scan_result):
    port_state = scan_result['scan'][host]['tcp']
    print("Command line:"+ scan_result['nmap']['command_line'])
    for key, value in port_state.items():
        print('Port {0} --> {1}'.format(key, value))

class NmapScannerAsync:
    def __init__(self):
        self.portScannerAsync = nmap.PortScannerAsync()

    def scanning(self):
        while self.portScannerAsync.still_scanning():
            print("Scanning >>>")
            self.portScannerAsync.wait(5)

    def nmapScanAsync(self, hostname, port):
        try:
            print("Checking port "+ port +" ..........")
            self.portScannerAsync.scan(hostname, arguments="-A -sV -p"+port ,callback=callbackResult)
            self.scanning()
        except Exception as exception:
            print("Error to connect with " + hostname + " for port scanning",str(exception))

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Asynchronous Nmap scanner')
    parser.add_argument("--host", dest="host", help="target IP / domain", required=True)
    parser.add_argument("-ports", dest="ports", help="Please, specify the target port(s) separated by comma[80,8080 by default]", default="80,8080")
    parsed_args = parser.parse_args()
    port_list = parsed_args.ports.split(',')
    host = parsed_args.host
    for port in port_list:
        NmapScannerAsync().nmapScanAsync(host, port)

內容解密:

  1. callbackResult 函式:當 Nmap 完成掃描後會呼叫此函式,顯示執行的指令和每個連線埠的狀態。
  2. NmapScannerAsync 類別:負責初始化非同步掃描器並執行掃描。
    • __init__ 方法:初始化 nmap.PortScannerAsync() 物件。
    • scanning 方法:持續檢查掃描是否完成,若未完成則等待。
    • nmapScanAsync 方法:對指定的主機和連線埠執行非同步掃描。
  3. 主程式:解析命令列引數,呼叫 nmapScanAsync 方法對每個指定的連線埠進行掃描。

使用 os 和 subprocess 模組執行 Nmap

除了使用 python-nmap 外,我們還可以直接利用 os 和 subprocess 模組執行 Nmap 指令。

使用 os 模組

import os
nmap_command = "nmap -sT 127.0.0.1"
os.system(nmap_command)

內容解密:

  • os.system 方法:執行指定的 Nmap 指令,並將結果直接輸出到控制檯。

使用 subprocess 模組

from subprocess import Popen, PIPE
process = Popen(['nmap','-O','127.0.0.1'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())

內容解密:

  • Popen 方法:建立一個新的程式執行 Nmap 指令,並捕捉其輸出。
  • communicate 方法:等待程式完成並取得其輸出結果。
  • stdout.decode():將輸出的位元組解碼為字串並列印出來。

發現服務與漏洞:Nmap 指令碼的應用

在前面的章節中,我們已經瞭解如何使用 ossubprocess 模組來執行 Nmap 命令,並取得關於目標主機的作業系統資訊。現在,我們將進一步探討如何使用 Nmap 指令碼來發現服務和漏洞。

使用 Nmap 指令碼發現服務

Nmap 的強大之處在於其指令碼引擎(NSE),允許使用者執行特定的測試,以收集目標主機的資訊。這些指令碼可以用於檢查服務的狀態、提取服務資訊,甚至檢測特定的漏洞,如 ShellShock、Poodle 或 HeartBleed。

Nmap 提供了多種型別的指令碼,包括:

  • Auth:執行所有可用的身份驗證指令碼
  • Default:執行預設的基本指令碼
  • Discovery:從目標主機檢索資訊
  • External:使用外部資源的指令碼
  • Intrusive:被視為對目標主機具有侵入性的指令碼
  • Malware:檢查是否存在惡意程式碼或後門開啟的連線
  • Safe:執行非侵入性的指令碼
  • Vuln:檢測最知名的漏洞
  • All:執行所有可用的 NSE 指令碼

在 Unix 系統中,這些指令碼通常位於 /usr/share/nmap/scripts 目錄下。

執行 Nmap 指令碼

要執行 Nmap 指令碼,需要在 Nmap 命令中使用 --script 選項。例如,使用 banner 指令碼來取得服務資訊:

$ sudo nmap -sSV --script banner scanme.nmap.org

內容解密:

  • -sSV 引數用於進行服務版本掃描。
  • --script banner 指定了要執行的指令碼名稱。
  • scanme.nmap.org 是掃描的目標主機。

輸出結果將顯示開放的埠,以及每個埠對應的服務版本和作業系統資訊。

探索服務和漏洞

另一個有用的指令碼是 discovery,它允許我們取得更多關於目標主機上執行服務的資訊:

$ sudo nmap --script discovery scanme.nmap.org

內容解密:

  • --script discovery 指定了要執行的 discovery 指令碼。
  • 輸出結果中包含了 DNS 暴力破解(dns-brute)的結果,用於取得子網域名稱及其 IP 地址。

此外,我們還可以使用 Nmap 指令碼來取得 SSH 埠上的公鑰和加密演算法資訊:

$ sudo nmap -sSV -p22 --script ssh-hostkey scanme.nmap.org

內容解密:

  • -p22 指定了要掃描的埠號(此處為 SSH 埠 22)。
  • --script ssh-hostkey 指定了要執行的指令碼,用於取得 SSH 主機金鑰。

輸出結果將顯示 SSH 服務的版本、支援的加密演算法以及公鑰資訊。