前言

    上一篇我们讲到利用python进行信息收集,此篇我们将要学习如何利用python的nmap模块来编写一些实用的扫描工具。初出茅庐,如有错误望各位不吝赐教。

3.1 概念

    端口扫描工具是用于检测计算机或网络上开放的端口的工具。以下是我们可以通过端口扫描工具获取什么信息:

  1. 安全评估:端口扫描工具可以用于评估计算机或网络的安全性。它可以帮助管理员发现可能存在的安全漏洞或开放的不必要的端口,从而采取相应的措施来加强安全性。
  2. 检测端口状态:端口扫描工具可以帮助管理员检测端口的状态,即确定端口是开放还是关闭。这对于识别网络中活动的服务和应用程序非常有用。
  3. 端口映射:端口扫描工具可以用于检测网络中的端口映射。它可以确定网络中的具体设备和端口之间的映射关系,帮助管理员更好地理解网络拓扑和配置。
  4. 故障诊断:端口扫描工具可以用于故障排除和排查网络或计算机的问题。通过检测端口状态和连接问题,管理员可以更快地找到问题的根源。

3.2 Nmap基本用法:

    Nmap库是一个用于扫描和探测网络主机的Python库。nmap库提供了一种简单的方法来执行nmap扫描,并解析扫描结果。它可以发送各种nmap扫描请求,如ping扫描、端口扫描、操作系统检测等。我们先来看看Python Nmap库的几个基本用法示例:

使用Python Nmap库进行端口扫描:

import nmap

# 创建Nmap PortScanner对象
scanner = nmap.PortScanner()

# 扫描指定IP的所有开放端口
result = scanner.scan('192.168.1.1', '1-1000')

# 打印扫描结果
print(result)

使用Python Nmap库进行服务和操作系统探测:

import nmap

# 创建Nmap PortScanner对象
scanner = nmap.PortScanner()

# 扫描指定IP的服务和操作系统信息
result = scanner.scan('192.168.1.1', arguments='-O')

# 打印扫描结果
print(result)

使用Python Nmap库进行漏洞扫描:

import nmap

# 创建Nmap PortScanner对象
scanner = nmap.PortScanner()

# 扫描指定IP的漏洞信息
result = scanner.scan('192.168.1.1', arguments='--script vuln')

# 打印扫描结果
print(result)

这里补充一下,scan方法的参数是用来指定nmap扫描的选项和参数的,有许多可选参数,那么常见的有以下几项:

  • arguments: 用来指定nmap的命令行参数。例如,-sS表示TCP SYN扫描,-sU表示UDP扫描,-p表示指定端口范围等等。可以根据需要传递不同的参数来进行不同类型的扫描。
  • ports: 用来指定要扫描的端口范围。可以传递单个端口号,或者使用连接符-来表示一个范围。例如,ports='80,443'表示扫描80和443端口,ports='1-1000'表示扫描1到1000之间的所有端口。
  • arguments_file: 可以将nmap参数保存到一个文件中,然后通过该参数指定文件路径,以便进行扫描。
  • sudo: 用于指定是否使用sudo权限来运行nmap。默认值为False,表示不使用sudo权限。如果需要进行特权扫描,则可以将该参数设置为True。
  • sudo_password: 如果需要使用sudo权限,可以通过该参数设置sudo密码。
  • scan_type: 用于指定扫描类型。可以是synudptcp等。根据不同的扫描类型,scan()方法会自动根据参数进行相应的配置。
  • callback_result: 可以在扫描完成后指定一个回调函数来处理扫描结果。回调函数接受一个参数,即nmap扫描结果。

 3.3 ping扫描

    ping扫描可用于测试主机的可达性。它发送一个ICMP Echo Request(ping)消息到目标主机,并等待目标主机返回一个ICMP Echo Reply(pong)消息作为响应。通过检查响应的时间和结果,我们就可以判断目标主机是否在线,以及网络延迟的情况。下面我们将利用Nmap模块来实现此功能:

import nmap

def ping_scan(hosts):
    nm = nmap.PortScanner()
    nm.scan(hosts, arguments='-sn')
    
    for host in nm.all_hosts():
        if nm[host]['status']['state'] == 'up':
            print(f'{host} is up')
        else:
            print(f'{host} is down')


if __name__ == "__main__":
    hosts = '192.168.0.1,192.168.0.2,192.168.0.3'
    ping_scan(hosts)

我们使用nmap.PortScanner()创建一个nmap扫描器对象。然后使用scan()方法扫描指定的主机。参数-sn表示只进行ping扫描。你可以根据需要添加其他nmap参数来进行更复杂的扫描操作。

之后,我们通过遍历nm.all_hosts()来获取扫描结果,如果主机状态为'up',则表示主机存活,否则表示主机宕机。

最后,在主程序的if __name__ == "__main__":部分,我们指定要扫描的主机列表,并调用ping_scan()函数进行扫描。

3.4 操作系统检测

    操作系统检测可以帮助安全专家识别潜在的漏洞或安全问题。不同的操作系统可能存在不同的安全风险和漏洞。以下是使用python-nmap进行操作系统检测的基本示例:

 1、导入所需的库和模块:

import nmap

2、创建一个NmapPortScanner对象:

nm = nmap.PortScanner()

3、使用scan()方法扫描目标IP:

target_ip = "192.168.0.1"
scan_results = nm.scan(hosts=target_ip, arguments='-O')

4、从扫描结果中获取操作系统信息:

os_info = scan_results['scan'][target_ip]['osmatch'][0]['osclass'][0]['osfamily']
print("操作系统:", os_info)

完整的示例代码如下所示:

import nmap

nm = nmap.PortScanner()

target_ip = "192.168.0.1"
scan_results = nm.scan(hosts=target_ip, arguments='-O')

os_info = scan_results['scan'][target_ip]['osmatch'][0]['osclass'][0]['osfamily']
print("操作系统:", os_info)

注:执行此代码需要在具有root或管理员权限的环境中,不然有可能导致获取信息不完整或报错。

3.5 检测网络中的端口映射

      检测网络中的端口映射是为了确定网络设备和服务的安全性。通过检测端口映射,可以确定网络上的哪些端口对公众可见,确保只有授权的服务和设备才能访问网络,通过确定哪些端口对外开放,可以识别潜在的攻击面和漏洞。

1、创建一个Nmap扫描器对象:

scanner = nmap.PortScanner()

2、使用scan()方法来扫描指定的目标IP地址:

scanner.scan('192.168.1.1', '1-1000')

上面的例子中,我们扫描了IP地址为192.168.1.1的主机的1到1000端口。

3、使用all_hosts()方法获取所有扫描到的主机列表:

hosts_list = scanner.all_hosts()

4、遍历主机列表,使用[host][proto].keys()来获取映射的端口列表:

for host in hosts_list:
    for proto in scanner[host].all_protocols():
        lport = scanner[host][proto].keys()
        for port in lport:
            print(f'Host: {host}, Port: {port}, State: {scanner[host][proto][port]["state"]}')

上述代码中,我们遍历主机列表,然后遍历每个主机的协议列表,获取映射的端口列表,并打印出端口、主机和状态信息。

这样,你就可以使用Python的Nmap库来检测网络中的端口映射了。记得在运行代码之前确保你有足够的权限来使用Nmap扫描器。

3.6主机存活/开放端口扫描

    最后要讲的应该是大家最耳熟能详的渗透工具功能了,通过检测主机或端口是否有回应来判断主机存活与端口开放情况,那么我们话不多说,来实现一下这个功能吧!

import nmap

def scan_ports(target_host, target_ports):
    nm = nmap.PortScanner()
    open_ports = []
    
    # 扫描指定主机的指定端口
    for target_port in target_ports:
        result = nm.scan(target_host, target_port)
        state = result['scan'][target_host]['tcp'][int(target_port)]['state']
        
        # 如果端口是开放的,则将其添加到开放端口列表中
        if state == 'open':
            open_ports.append(target_port)
    
    return open_ports

def scan_hosts(target_hosts, target_ports):
    nm = nmap.PortScanner()
    alive_hosts = []
    
    # 扫描指定主机的存活状态
    for target_host in target_hosts:
        result = nm.scan(target_host, arguments='-sn')
        state = result['scan'][target_host]['status']['state']
        
        # 如果主机存活,则将其添加到存活主机列表中
        if state == 'up':
            alive_hosts.append(target_host)
    
    # 对存活主机进行端口扫描
    for host in alive_hosts:
        open_ports = scan_ports(host, target_ports)
        print(f'Open ports on {host}: {open_ports}')

# 例子使用
target_hosts = ['192.168.0.1', '192.168.0.2']
target_ports = ['80', '443', '22']

scan_hosts(target_hosts, target_ports)

注:使用此代码进行扫描可能需要管理员权限。