【网络攻防课实验】五:Nmap脚本引擎 (NSE) 的使用及脚本编写


实验简述

Nmap具有强大的脚本引擎NSE(Nmap Scripting Engine),它允许用户编写(和共享)简单的脚本(使用lua编程语言)自动化各种网络任务。

本次实验目的在于掌握Nmap脚本的基本使用方法。

实验环境

kali,IP地址:192.168.11.11

Linux,IP地址:192.168.11.21

实验内容

1、初识NSE

Nmap提供的脚本相关命令行参数如下:

  • -sC: 等价于–script=default,使用默认类别的脚本进行扫描 可更换其他类别
  • –script=: 使用某个或某类脚本进行扫描,支持通配符描述
  • –script-args=<n1=v1,[n2=v2,…]>: 为脚本提供默认参数
  • –script-args-file=filename: 使用文件来为脚本提供参数
  • –script-trace: 显示脚本执行过程中发送与接收的数据
  • –script-updatedb: 更新脚本数据库
  • –script-help=: 显示脚本的帮助信息,其中部分可以逗号分隔的文件或脚本类别

该步骤简单介绍脚本的相关使用。

在使用Nmap时,通过--script=脚本名语句来调用脚本,而且Nmap自带众多脚本,路径如下:
在这里插入图片描述
这些脚本大致分为以下几种:

  • auth 处理身份验证
  • broadcast 网络广播
  • brute 暴力猜解
  • default 默认
  • discovery 服务发现
  • dos 拒绝服务
  • exploit 漏洞利用
  • external 外部扩展
  • fuzzer 模糊测试
  • intrusive 扫描可能造成不良后果
  • malware 检测后门
  • safe 扫描危害较小
  • version 版本识别
  • vuln 漏洞检测

在调用脚本时,可以使用种类名来调用该分类下的全部脚本,如--scritp vuln,但是比较费时间,在此就不演示,本次以 http-methods 脚本为例,来演示脚本的大致使用。

使用--script-help脚本名来查看脚本的说明和用法,比如查看 http-methods.nse 脚本信息:
在这里插入图片描述
使用http-methods.nse脚本来对目标主机进行探测,用于得到目标支持的http请求方式

nmap --script-help=http-methods 192.168.11.21

在这里插入图片描述
可以看到探测出来目标主机支持的http请求有 GET、POST、HEAD、OPTIONS 四种。

因为所有的脚本都是以服务名来命名,比如 http 相关的脚本就是 http 开头,ssl 相关脚本是以 ssl开头:
在这里插入图片描述
因此在调用脚本时,可以使用通配符 * 来调用相关服务下的所有脚本,以mysql服务为例,所有mysql脚本如下:
在这里插入图片描述
使用语句 --script "mysql*" 来选择mysql相关的所有脚本,探测结果如下:

nmap --script "mysql*" 192.168.11.21

在这里插入图片描述

2、NSE参数

Nmap在使用脚本时,如果脚本支持,我们还可以通过 --script-args 传入参数。

已知一些网站会通过判断 user-agent 来判断请求是否合法,那Nmap在请求时有没有带上自己的特征呢?同样使用刚才的 http-methos.nse 脚本,打开wireshark抓包,启动以下命令:

nmap --script=http-methods.nse 192.168.11.21

在这里插入图片描述
可以看到在请求包的 User-Agent 字段信息包含 Nmap Scripting Engine,也就是代表该请求来自 Nmap的脚本,如果目标主机对该请求进行了过滤,那么就无法成功探测。

因此需要加入一定的参数,来改变 User-Agent 字段信息,绕过过滤,使用 --script-args 修改 User-Agent 的值

命令如下:

nmap --script=http-methods --script-args http.useragent="Mozilla 42" 192.168.11.21

在这里插入图片描述
重新抓包,发现 User-Agent 字段内容已经更改
在这里插入图片描述
还有其他脚本参数,后续继续学习。

3、输出细节

在使用脚本时,可以添加 --script-trace 参数来打印出所有交互数据包的细节

nmap --script=http-methods --script-trace 192.168.11.21

在这里插入图片描述
使用 -d1-9 来进入调试模式,查看扫描信息,数字越大,输出越详细,以 d2 为例:

nmap --script=http-methods -d2 192.168.11.21

在这里插入图片描述

4、脚本格式

Nmap脚本使用 lua 语言编写,采用严格的格式规范,一个完整的NSE包括以下几个部分:

  • 引用API(local aaa require(“aaa”))
  • description字段:脚本的介绍及描述
  • author字段:作者信息
  • categories字段:脚本分类信息
  • rule字段:脚本触发执行的条件
  • action字段:脚本执行内容

依然以 http-methods.nse 脚本为例,来展示nse的组成:

1.引用API部分:使用 require 函数调用模块
在这里插入图片描述
2.description字段:脚本的介绍及描述
在这里插入图片描述
3.author字段:作者信息
在这里插入图片描述
4.categories字段:脚本分类信息
在这里插入图片描述
5.rule字段:描述脚本执行的规则,也就是确定脚本触发执行的条件,这个规则是一个lua函数,返回值只有true和false两种,只有返回true时,action中的函数才会执行
在这里插入图片描述
6.action字段:脚本具体的执行内容,当脚本通过rule字段的检查被触发执行时,就会调用action字段定义的函数
在这里插入图片描述
Nmap的扩展脚本语言都基于lua来开发的,执行也是调用了内部封装的lua解释器。正常情况下,调用任何一个扩展脚本会首先执行nse_main.lua,该脚本主要做了以下几件事:

  • 加载一些Nmap的核心库(nselib文件夹中)

    定义多线程函数

    定义输出结果处理函数

    读取、加载扩展脚本

    定义扩展脚本函数接口

    执行扩展脚本

扩展脚本执行的规则在nse_main.lua中有定义:
在这里插入图片描述
具体的执行规则如下:

  • prerule:在扫描任何主机之前,prerule函数运行一次
  • hostrule:在扫描一个主机后运行一次
  • portrule:在扫描一个主机的端口后运行一次
  • postrule:在全部扫描完毕以后运行一次

可以编写一个nse文件进行简单的验证:
在这里插入图片描述
其中action函数是在 hostrule 或 portsule 返回 true 时,才会,因为 prerule 和 postrule 没有判断条件。

执行结果如下:
在这里插入图片描述
也就是说,

  • prerule 和 postrule 是在开始和结束运行,并且只运行一次
  • hostrule 是扫描一个主机就运行一次,有N个主机就会运行N次
  • portrule 是扫描到一个端口就运行一次,有N个端口就运行N次

了解了这些后,我们试着编写一个简单的脚本,来体验一下NSE的功能。

5、编写脚本

在开始编写脚本之前,还应该对NSE中数据的传递做简单了解

在脚本引擎中,用户可以轻松访问Nmap已经了解的有关目标主机的信息。该数据作为参数传递给NSE脚本的 action 方法,参数 host 和 port 是 lua 表,其中包含脚本执行的目标的信息。

每个表里面所含有的变量:

host 表:

host:
该表作为参数传递给规则和操作功能。
host.os:
操作系统匹配表数组。
host.ip:
包含目标主机IP地址的字符串表示形式。
host.nam:
包含表示为字符串的扫描目标主机的反向DNS条目。
host.targetname:
包含在命令行上指定的主机名。
host.reason:
包含目标主机为何处于其当前状态的原因的字符串表示形式。
host.reason_ttl:
包含响应数据包的TTL值,用于确定目标主机到达时的状态。
host.directly_connected:
一个布尔值,指示目标主机是否直接连接到运行Nmap的主机(即与该主机处于同一网段)。
host.mac_addr:
MAC地址 目标主机的名称(六字节长的二进制字符串)(如果有),否则nil。
host.mac_addr_next_hop:
到主机的路由中第一跳的MAC地址,或者 nil如果不可用。
host.mac_addr_src:
我们自己的MAC地址,用于连接到主机(我们的网卡或(带有 --spoof-mac) 欺骗性地址)。
host.interface:
包含接口名称的字符串(dnet样式) 通过它向主机发送数据包。
host.interface_mtu:
MTU(最大传输单位)host.interface,如果未知,则为0。
host.bin_ip:
目标主机的IP地址为4字节(IPv4)或16字节(IPv6)字符串。
host.bin_ip_src:
我们主机的(正在运行的Nmap)源IP地址为4字节(IPv4)或16字节(IPv6)字符串。
host.times:
该表包含主机的Nmap时序数据。
host.traceroute:
这是使用该–traceroute选项时出现的traceroute跃点数组。
host.os_fp:
如果执行了OS检测,则这是一个字符串,其中包含主机的OS指纹。

port 表:

port.number:
目标端口的端口号。
port.protocol:
目标端口的协议,有效值为 “tcp"和"udp”。
port.service:
包含 port.numberNmap 服务检测所检测到的正在运行的服务的字符串表示形式 。
port.reason:
包含目标端口为何处于其当前状态的原因的字符串表示形式(由提供port.state)。
port.reason_ttl:
包含响应数据包的TTL值,用于确定目标端口到达时的状态。此响应数据包是也用于设置的数据包port.reason。
port.state:
包含有关端口状态的信息。服务脚本只能再次运行。
port.version相关:
此项是一个表,其中包含Nmap版本扫描引擎检索到的信息。

参考 Nmap官方文档:https://nmap.org/book/nse-api.html

了解了NSE中数据的传递,尝试写一个简单的脚本。

实现的功能是当发现目标开放端口后,便输出"IP *** open *** port"的语句,严格按照格式来编写一个完整的脚本:
在这里插入图片描述

description = [[
this is my fisrt nmap script.
]]

author = {"wx"}

categories = {"default"}

portrule = function(host, port)
	return true
end

action = function(host, port)
	return string.format("IP <%s> open <%d> port", host.ip, port.number)
	       -- "IP".. host .."open".. port.number .."port"
end

运行结果:
在这里插入图片描述
那如果想在指定端口下输出结果呢?以 80 端口为例,此时代码如下:
在这里插入图片描述
只需要返回指定的端口,即当判断是 80 端口时,就会返回True,然后执行 action 函数。

运行结果:
在这里插入图片描述
至此,实验基本结束。

实验总结

本次实验了解了Nmap的脚本引擎NSE,学习了在Nmap中如何使用脚本以及脚本的编写,通过学习编写了简单的测试脚本。

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