探索和创建 Nmap 脚本

NmapNmapBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本次实验中,你将了解 Nmap 的脚本引擎(NSE),以及如何对 Nmap 脚本进行分类和更新。Nmap 是一款强大的开源网络发现和安全审计工具,其功能通过 NSE 得到了扩展。NSE 允许用户编写和共享用于自动化各种网络任务的脚本。

本次实验将指导你探索 Nmap 的脚本类别、创建自定义脚本目录、添加你自己的脚本,以及更新 Nmap 脚本数据库。这些技能对于网络管理员和安全专业人员高效地扫描网络并识别漏洞至关重要。

探索 Nmap 脚本类别

在这一步中,你将探索系统中预安装的 Nmap 脚本类别。Nmap 脚本是网络安全领域的强大工具,它们根据功能进行组织。例如,有些脚本用于发现(discovery),这意味着它们可以在网络中查找设备和服务;其他脚本用于漏洞评估(vulnerability assessment),有助于识别系统中的安全弱点。

首先,你需要打开一个终端。终端是一个基于文本的界面,你可以在其中输入命令与系统进行交互。终端打开后,你需要确保位于正确的目录。目录就像计算机上存储文件和其他文件夹的文件夹。在终端中运行以下命令:

cd /home/labex/project

此命令将当前工作目录更改为 /home/labex/project

现在,让我们检查系统上安装的 Nmap 版本。了解版本很重要,因为不同版本可能具有不同的功能和兼容性。在终端中运行此命令:

nmap --version

输出将类似于以下内容:

Nmap version 7.80 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.3.3 openssl-1.1.1f libpcre-8.39 libpcap-1.9.1 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

接下来,我们将查看可用的 Nmap 脚本类别。Nmap 脚本存储在 /usr/share/nmap/scripts/ 目录中。为了了解有哪些脚本可用,我们可以列出它们并按名称排序。在终端中运行此命令:

ls /usr/share/nmap/scripts/ | grep -v .lua | sort | head -10

此命令首先列出 /usr/share/nmap/scripts/ 目录中的所有文件,然后使用 grep -v .lua 排除具有 .lua 扩展名的文件,之后按名称对剩余文件进行排序并显示前 10 个结果。输出将类似于:

address-info.nse
afp-brute.nse
afp-ls.nse
afp-path-vuln.nse
afp-serverinfo.nse
afp-showmount.nse
ajp-auth.nse
ajp-brute.nse
ajp-headers.nse
ajp-methods.nse

要查看所有脚本类别,我们可以使用以下命令:

grep -r categories /usr/share/nmap/scripts/*.nse | grep -o "categories = {[^}]*}" | sort | uniq | head -10

此命令在 /usr/share/nmap/scripts/ 目录中的所有 .nse 脚本文件中搜索 "categories" 字符串,然后提取类别信息,对其进行排序,删除任何重复条目,并显示前 10 个结果。输出将类似于:

categories = {"auth", "brute", "intrusive"}
categories = {"auth", "default", "discovery", "safe"}
categories = {"auth", "discovery", "safe"}
categories = {"auth", "intrusive"}
categories = {"auth", "safe"}
categories = {"broadcast", "discovery"}
categories = {"broadcast", "discovery", "safe"}
categories = {"default", "discovery"}
categories = {"default", "discovery", "safe"}
categories = {"default", "discovery", "safe", "version"}

为了更好地组织脚本,我们将创建一个目录结构,根据脚本的功能对其进行分类。这将使你以后更容易找到和使用这些脚本。我们将为不同的类别创建单独的目录。在终端中运行以下命令:

mkdir -p /home/labex/project/NmapScripts/vulnerability
mkdir -p /home/labex/project/NmapScripts/discovery
mkdir -p /home/labex/project/NmapScripts/authentication

mkdir -p 命令用于创建目录。如果父目录不存在,它也会创建这些父目录。

现在,让我们将一些与漏洞相关的脚本复制到新创建的漏洞目录中。在终端中运行此命令:

cp /usr/share/nmap/scripts/smb-vuln* /home/labex/project/NmapScripts/vulnerability/

此命令将 /usr/share/nmap/scripts/ 目录中所有名称以 smb - vuln 开头的脚本复制到 /home/labex/project/NmapScripts/vulnerability/ 目录中。

让我们验证文件是否已正确复制。在终端中运行此命令:

ls -la /home/labex/project/NmapScripts/vulnerability/

输出将显示复制的漏洞脚本:

total 88
drwxr-xr-x 2 labex labex  4096 Mar 15 12:30 .
drwxr-xr-x 4 labex labex  4096 Mar 15 12:30 ..
-rw-r--r-- 1 labex labex  3355 Mar 15 12:30 smb-vuln-conficker.nse
-rw-r--r-- 1 labex labex  8045 Mar 15 12:30 smb-vuln-cve2009-3103.nse
-rw-r--r-- 1 labex labex  5100 Mar 15 12:30 smb-vuln-cve-2017-7494.nse
-rw-r--r-- 1 labex labex  9595 Mar 15 12:30 smb-vuln-ms06-025.nse
-rw-r--r-- 1 labex labex 11645 Mar 15 12:30 smb-vuln-ms07-029.nse
-rw-r--r-- 1 labex labex 12558 Mar 15 12:30 smb-vuln-ms08-067.nse
-rw-r--r-- 1 labex labex  9719 Mar 15 12:30 smb-vuln-ms10-054.nse
-rw-r--r-- 1 labex labex  7326 Mar 15 12:30 smb-vuln-ms10-061.nse
-rw-r--r-- 1 labex labex  8091 Mar 15 12:30 smb-vuln-ms17-010.nse
-rw-r--r-- 1 labex labex  4245 Mar 15 12:30 smb-vuln-regsvc-dos.nse

同样,让我们将一些发现和认证脚本复制到各自的目录中。在终端中运行以下命令:

cp /usr/share/nmap/scripts/dns-* /home/labex/project/NmapScripts/discovery/
cp /usr/share/nmap/scripts/ssh-* /home/labex/project/NmapScripts/authentication/

现在,你已经根据功能将一些 Nmap 脚本分类,这使得你更容易找到并将它们用于特定任务。

理解脚本功能

在这一步中,你将学习如何检查和理解 Nmap 脚本,以了解它们的功能。了解这些非常重要,因为这有助于你为不同的网络扫描任务选择合适的脚本。

让我们从仔细查看上一步中复制的一个漏洞脚本开始。你可以使用 cat 命令显示脚本的内容,然后使用 head -20 仅显示前 20 行。这样,你可以快速查看脚本开头的重要信息。

cat /home/labex/project/NmapScripts/vulnerability/smb-vuln-ms17-010.nse | head -20

输出将显示脚本的开头部分。这部分通常包含脚本的用途和使用方法的详细信息。

local smb = require "smb"
local vulns = require "vulns"
local stdnse = require "stdnse"
local string = require "string"

description = [[
Attempts to detect if a Microsoft SMBv1 server is vulnerable to a remote code
execution vulnerability (ms17-010, a.k.a. EternalBlue). The vulnerability affects
Windows Vista, 7, 8.1, 10, Server 2008, Server 2008 R2, Server 2012 Gold and R2, and Server 2016.

The script connects to the $IPC tree, executes a transaction on FID 0 and
checks if the error "STATUS_INSUFF_SERVER_RESOURCES" is returned to
determine if the target is not patched against ms17-010. Additionally it checks
for a matching error code on EternalChampion.

References:
* https://technet.microsoft.com/en-us/library/security/ms17-010.aspx
* https://blogs.technet.microsoft.com/msrc/2017/05/12/customer-guidance-for-wannacrypt-attacks/
* https://msrc-blog.microsoft.com/2017/05/12/customer-guidance-for-wannacrypt-attacks/
* https://github.com/rapid7/metasploit-framework/pull/8654/files

这个脚本旨在检查 Microsoft SMBv1 服务器是否存在 MS17 - 010 漏洞,也就是所谓的“永恒之蓝”(EternalBlue)漏洞。

现在,让我们来看看 Nmap 脚本的结构,以了解它的不同部分。大多数 Nmap 脚本都有以下关键组件:

  1. 描述部分(description section):这部分会告诉你脚本的功能,就像一个简短的摘要,帮助你快速了解脚本的用途。
  2. 作者部分(author section):这部分会列出脚本的创作者。了解脚本的作者很重要,特别是当你需要联系他们或查找同一作者的其他脚本时。
  3. 类别(categories):这些类别将相似的脚本归为一组。例如,与漏洞扫描相关的脚本可能属于“vuln”类别。这使得查找和管理脚本更加容易。
  4. 规则(rules):这些规则决定了脚本何时运行。有不同类型的规则,如 portrulehostrule。例如,hostrule 可以指定脚本仅在某些主机上运行。
  5. 主操作函数(main action function):这是脚本实际执行任务的地方。它包含执行任务的代码,如检查漏洞或获取主机信息。

让我们创建一个基本的 Nmap 脚本来实际了解这种结构。你可以使用 cat 命令创建一个新文件,并将脚本写入其中。

cat << 'EOF' > /home/labex/project/my-ping-check.nse
description = [[
A simple script that checks if a host responds to ICMP echo requests (ping).
]]

author = "LabEx User"

categories = {"discovery", "safe"}

-- The rule section determines when the script should be run
hostrule = function(host)
  return true  -- Run the script for all hosts
end

-- The action section contains the main function of the script
action = function(host)
  local output = "Host status: "
  
  if host.pingresponse then
    output = output .. "Responds to ping"
  else
    output = output .. "Does not respond to ping"
  end
  
  return output
end
EOF

让我们来分析一下这个脚本:

  • description 部分清楚地说明了该脚本用于检查主机是否响应 ping 请求。
  • author 部分表明该脚本是由 LabEx 用户创建的。
  • categories 部分将此脚本与其他发现类和安全类脚本归为一组。发现类脚本用于查找主机信息,而安全类脚本是指不会对目标造成任何损害的脚本。
  • hostrule 函数设置为返回 true,这意味着该脚本将在所有主机上运行。
  • action 函数包含主要逻辑。它检查主机是否有 ping 响应,然后返回一条消息,指示主机是否响应 ping 请求。

现在,让我们针对本地主机(127.0.0.1)运行我们的自定义脚本。你可以使用 nmap 命令和 --script 选项来指定自定义脚本。

nmap --script /home/labex/project/my-ping-check.nse 127.0.0.1

你应该会看到类似于以下的输出:

Starting Nmap 7.80 ( https://nmap.org )
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000091s latency).
Not shown: 998 closed ports
PORT     SERVICE SERVICE
22/tcp   open  ssh
| my-ping-check: Host status: Responds to ping
3001/tcp open  nessus
|_my-ping-check: Host status: Responds to ping

Nmap done: 1 IP address (1 host up) scanned in 0.24 seconds

这个输出表明你的脚本运行正常。它检测到本地主机响应 ping 请求。这是一个简单的示例,但它展示了 Nmap 脚本的基本结构和功能。

创建自定义 Nmap 脚本并将其添加到 Nmap 中

在这一步中,你将学习如何创建自定义的 Nmap 脚本,并将其添加到 Nmap 脚本数据库中。Nmap 是一款强大的网络扫描工具,通过添加自定义脚本,你可以扩展其功能,以满足特定需求。这意味着你可以在网络扫描过程中执行默认 Nmap 脚本未涵盖的独特任务。

首先,让我们创建一个新的、稍微复杂一些的脚本。这个脚本将检查特定端口是否开放。端口就像是网络中的门,它们允许不同类型的网络流量进出设备。通过检查端口是否开放,你可以了解设备上是否运行着特定的服务。

cat << 'EOF' > /usr/share/nmap/scripts/port-check.nse
description = [[
A script that checks if a specific port is open and reports its status.
]]

author = "LabEx User"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}

-- The portrule determines when the script should be run
portrule = function(host, port)
  return port.protocol == "tcp" and port.state == "open"
end

-- The action section contains the main function of the script
action = function(host, port)
  local output = string.format("Port %d is open on host %s", port.number, host.ip)
  return output
end
EOF

在上述代码中,你首先定义了脚本的功能描述,然后设置了作者和许可证信息。portrule 函数决定了脚本何时运行,这里它会检查端口是否使用 TCP 协议且处于开放状态。action 函数是脚本的主要部分,它会创建一条消息,表明特定主机上的某个端口是开放的。

注意,你直接在 Nmap 脚本目录(/usr/share/nmap/scripts/)中创建了这个脚本。这很重要,因为 Nmap 会在这个目录中查找脚本。然而,仅仅创建脚本是不够的,Nmap 需要知道这个新脚本的存在,所以你需要更新 Nmap 脚本数据库。

要更新 Nmap 脚本数据库,请运行以下命令:

sudo nmap --script-updatedb

输出应该类似于:

Starting Nmap 7.80 ( https://nmap.org )
NSE: Updating rule database.
NSE: Script Database updated successfully.
Nmap done: 0 IP addresses (0 hosts up) scanned in 0.36 seconds

这个输出表明脚本数据库已成功更新。现在,让我们验证脚本是否已添加到 Nmap 脚本数据库中。你可以通过在 script.db 文件中搜索脚本来完成此操作。

grep port-check /usr/share/nmap/scripts/script.db

你应该会看到类似于以下的输出:

Entry { filename = "port-check.nse", categories = { "discovery", "safe", } }

这证实了脚本已成功添加到 Nmap 脚本数据库中。

现在,让我们再创建一个脚本,展示如何在 Nmap 脚本中使用库。库是预先编写好的代码,你可以使用它们来增强脚本的功能。这个脚本将检查 Web 服务器的 HTTP 头信息。HTTP 头包含有关网页的重要信息,如服务器类型、最后修改日期等。

cat << 'EOF' > /usr/share/nmap/scripts/http-headers-check.nse
description = [[
A script that retrieves and displays HTTP headers from web servers.
]]

author = "LabEx User"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}

local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"

-- The portrule determines when the script should be run
portrule = function(host, port)
  return shortport.http(host, port)
end

-- The action section contains the main function of the script
action = function(host, port)
  local response = http.get(host, port, "/")
  
  if not response or not response.status then
    return "Failed to retrieve HTTP headers"
  end
  
  local output = stdnse.output_table()
  output["Status"] = response.status
  
  if response.header then
    output["Headers"] = {}
    for name, value in pairs(response.header) do
      output["Headers"][name] = value
    end
  end
  
  return output
end
EOF

这个脚本使用了几个 Nmap 库:

  • http 用于发起 HTTP 请求。这个库允许脚本与 Web 服务器进行通信并获取信息。
  • shortport 用于确定端口是否可能运行 HTTP 服务。它帮助你判断主机上的特定端口是否用于 Web 流量。
  • stdnse 用于格式化输出。这使得从 Web 服务器获取的信息更易于阅读。

让我们再次更新脚本数据库,以便 Nmap 知晓新脚本:

sudo nmap --script-updatedb

现在,让我们针对 Web 服务器运行新脚本。为了演示,你将使用运行在 3001 端口(开发服务器常用端口)的本地 Web 服务器。

nmap --script http-headers-check -p 3001 127.0.0.1

如果 3001 端口上没有运行 Web 服务器,输出将表明该端口已关闭或被过滤。如果有 Web 服务器,你将看到检索到的 HTTP 头信息。

最后,让我们一起运行这两个自定义脚本。这样,你可以同时看到两个脚本的结果。

nmap --script "port-check,http-headers-check" -p 22,3001 127.0.0.1

这个命令将针对本地主机的 22 端口和 3001 端口运行这两个自定义脚本。22 端口通常用于 SSH(安全外壳)连接。

输出将显示这些端口是否开放,如果 3001 端口运行着 HTTP 服务,还将显示 HTTP 头信息。

通过创建自定义脚本并将其添加到 Nmap 中,你可以扩展其功能,以执行网络扫描和安全评估所需的特定任务。

按类别运行脚本并管理脚本输出

在这一步中,你将学习如何按类别运行 Nmap 脚本,并管理这些脚本扫描的输出。这是一项非常实用的技能,因为它允许你运行多个相关脚本,而无需分别指定每个脚本。

Nmap 脚本根据其功能被分为不同的类别。了解这些类别有助于你快速找到并运行所需的脚本。以下是一些常见的类别:

  • auth:这些是与身份验证相关的脚本。它们可以帮助你检查目标上的身份验证机制是否安全。
  • broadcast:此类别中的脚本会在本地网络上发送广播。它们对于发现同一网络上的设备和服务很有用。
  • brute:这些是暴力破解密码审计脚本。它们尝试不同的密码,看是否能未经授权访问服务。
  • default:当你在 Nmap 中使用 -sC 选项时,默认运行的就是这些脚本。它们为基本扫描提供了一个很好的起点。
  • discovery:这些脚本用于主机和服务发现。它们可以找出网络上有哪些主机以及它们正在运行哪些服务。
  • dos:拒绝服务(Denial of Service)脚本旨在使目标系统过载并使其不可用。使用这些脚本时要小心,因为它们可能会造成实际损害。
  • exploit:利用(Exploitation)脚本用于利用系统中已知的漏洞。它们可用于安全测试,但应谨慎使用。
  • external:这些脚本可能会将数据发送到第三方数据库。它们可以提供有关目标的额外信息,但你需要注意隐私问题。
  • fuzzer:模糊测试(Fuzzer)脚本使用模糊测试技术。它们向目标发送随机或格式错误的数据,看是否会导致错误或暴露漏洞。
  • intrusive:此类别中的脚本可能会导致服务崩溃或被视为具有侵入性。使用时要谨慎,尤其是在生产环境中。
  • malware:恶意软件检测脚本用于检查目标系统是否感染了恶意软件。
  • safe:这些脚本被认为是安全且非侵入性的。它们不会对目标系统造成任何损害。
  • version:版本检测脚本可帮助你找出目标服务上运行的软件版本。这些信息对于识别潜在漏洞很有用。
  • vuln:漏洞检测脚本用于查找目标系统中的安全弱点。

现在,让我们看看如何运行特定类别的脚本。例如,如果你想运行“discovery”类别中的所有脚本,可以使用以下命令:

nmap --script discovery 127.0.0.1

此命令告诉 Nmap 对本地主机(127.0.0.1)运行所有发现类脚本。输出会很长,因为它显示了所有发现类脚本的结果。

有时,你可能想运行多个类别的脚本。你可以使用逗号分隔类别名称来实现。以下是一个示例:

nmap --script "discovery,safe" -p 1-100 127.0.0.1

此命令对本地主机的 1 - 100 端口运行发现类和安全类的所有脚本。

你还可以使用 not 运算符排除特定类别。例如:

nmap --script "discovery and not broadcast" 127.0.0.1

此命令运行发现类脚本,但排除那些同时属于广播类别的脚本。

接下来,让我们看看格式化和保存 Nmap 脚本扫描输出的不同方法。Nmap 提供了几种输出格式,适用于不同的目的:

  1. 普通输出(默认):这是 Nmap 在屏幕上显示的标准文本输出。
  2. XML 输出:XML 是一种结构化格式,可被其他工具轻松解析。
  3. 可 grep 输出:这种格式设计为便于使用 grep 等工具进行搜索。
  4. JSON 输出(使用相应的脚本):JSON 是另一种广泛用于数据交换的结构化格式。

要将输出保存为 XML 格式,可以使用以下命令:

nmap --script vuln -p 1-1000 127.0.0.1 -oX /home/labex/project/scan_results.xml

此命令对本地主机的 1 - 1000 端口运行所有漏洞类脚本,并将结果以 XML 格式保存到文件 /home/labex/project/scan_results.xml 中。

让我们检查一下 XML 文件的内容:

head -20 /home/labex/project/scan_results.xml

此命令显示 XML 格式输出的前 20 行。你将看到有关扫描、使用的选项和扫描结果的信息。

对于可 grep 输出,可以使用以下命令:

nmap --script "default" 127.0.0.1 -oG /home/labex/project/scan_results.gnmap

此命令将结果保存为一种易于使用 grep 等工具解析的格式。

让我们检查一下 gnmap 文件的内容:

cat /home/labex/project/scan_results.gnmap

你会看到每个主机都在一行上,这使得搜索特定信息变得容易。

如果你想同时将输出保存为普通格式和 XML 格式,可以使用以下命令:

nmap --script "default" 127.0.0.1 -oX /home/labex/project/scan_results2.xml -oN /home/labex/project/scan_results.txt

此命令同时将输出保存为普通文本格式和 XML 格式。

最后,你可以使用 -oA 选项一次将输出保存为三种格式(普通、XML 和可 grep):

nmap --script "default" 127.0.0.1 -oA /home/labex/project/all_formats

此命令会创建三个文件:

  • /home/labex/project/all_formats.nmap(普通输出)
  • /home/labex/project/all_formats.xml(XML 输出)
  • /home/labex/project/all_formats.gnmap(可 grep 输出)

通过掌握这些按类别运行脚本和管理脚本输出的技术,你可以高效地进行网络扫描,并整理结果以进行进一步分析。

总结

在本次实验中,你学习了使用 Nmap 脚本引擎(NSE)的重要技能。你了解了如何根据功能对 Nmap 脚本进行分类和组织,这对于高效的网络扫描和安全评估至关重要。

你在多个方面获得了实践经验,包括探索脚本类别、创建有组织的目录、理解脚本结构、创建自定义脚本、将其添加到数据库、使用逻辑运算符按类别运行脚本,以及以不同格式管理输出。这些技能使你能够根据特定需求扩展 Nmap 的功能。通过掌握脚本创建、分类和更新,你可以开发更有针对性和高效的扫描工作流程。组织和格式化扫描结果的能力对于文档记录以及与团队成员和利益相关者的沟通也很有用。在你继续使用 Nmap 的过程中,可以基于这些技能开发更复杂的脚本和扫描策略。