nmap NSE脚本研究之二:脚本扫描阶段和执行rule函数

这一部分的东西可以耐心的看看,有利于理解NSE扫描原理和nmap原理。以下部分如有错误望指正。。

为了验证脚本扫描阶段和rule函数执行逻辑。。我写了一个小脚本,大家可以执行看看:

# cat test.nse 
local stdnse = require "stdnse"

prerule =  function()
    stdnse.debug1("=======================prerule")
  return nmap.is_privileged() and
    (stdnse.get_script_args("targets-sniffer.iface") or nmap.get_interface())
end
postrule = function()
    stdnse.debug1("=======================postrule")
  return false
end

portrule = function()
    stdnse.debug1("=======================portrule")
  return false
end
hostrule = function()
    stdnse.debug1("=======================hostrule")
  return false
end

action = function(host,port)
  print("=======================action")
end

 

NSE脚本参数arguments

命令行指定参数

有些脚本是有参数的,不指定参数脚本执行会失败,具体参数是什么以及怎么使用,可以直接查看脚本文件。

举例说明:

$nmap -p80 --script http-trace --script-args http-trace.path <target>

#可以忽略参数的脚本名称

$nmap -p80 --script http-trace --script-args path <target>

#如果多个脚本的argument名称相同,必须进行区别

$nmap --script script_1,script_2 --script-args script_2.uri=/axis2/,uri=/majordomo/ <target>

$nmap --script script_1,script_2 --script-args uri=/axis2/,script_1.uri=/majordomo/ <target>

$nmap --script script_1,script_2 --script-args script_2.uri=/axis2/,script_1.uri=/majordomo/ <target>

文件中定义参数

将参数写到文件中并引用,可以避免重复指定参数。

--script-args-file option 可以指定一个绝对路径或者相对路径的参数文件,供脚本使用,例如:

nmap --script "discovery,broadcast" --script-args-file nmap-args.txt <target>

The nmap-args.txt file are as follows:

http.useragent=Not Nmap

http.max-connections=50

userdb=/path/to/usernames.lst

passdb=/path/to/dictionary.lst

强制执行NSE脚本

NSE脚本是针对特定服务设计的,并不是所有端口都执行NSE脚本,这个根据[W用1] 著名端口、发现的服务类型进行对应。后面随着研究深入,这里的强制执行并没有那么简单,在单个target上,强制执行会忽略该Script的所有rule函数(如果有的话),不执行rule函数代码,强制return true。

所以,这里强制执行NSE脚本需要慎用。

$nmap --script +<script selection> <<arg1, arg2, …>

$nmap --script +http-title -p1212 192.168.x.x

调试脚本

如果需要分析NSE发送和接收的流量,则使用--script-trace选项打开NSE的调试模式。

注释:

--script-trace如果要生效,必须配置--script选项

--script-trace包含所有的发送和接收的数据包,不仅仅是NSE发送和接收的。。这有点像--packet-trace

如果您希望在漏洞利用类别中查看NSE脚本发送的有效负载,则可以使用以下表达式:

#nmap --script exploit --script-trace <target>

在使用--script-trace的同时,可以配合使用-d选项,打开nmap的调试模式,指定-d[1-9],设置级别越高,显示的信息越丰富。

 

扫描阶段和NSE

Nmap扫描分为11个阶段,但NSE仅涉及其中三个阶段:Script pre-scanning、Script scanning、Script post-scanning。这三个阶段只要指定--script 或 -sC 就会被执行。

扫描阶段

Scan Phases

开启选项

跳过选项

描述

脚本预扫描

Script pre-scanning

-sC or --script

default

只有在使用-sC或--script选项时才执行预扫描阶段;它试图通过一组NSE脚本检索主机的附加信息。当然在script中必须有prerule代码块才行。

目标枚举

Target enumeration

default

default

在此阶段,Nmap将一个或多个目标解析为IP地址。

主机发现

Host discovery

default

-Pn

在此阶段,Nmap通过指定的主机发现技术,检测目标是否存活

反向DNS解析

Reverse DNS resolution

default

-n

在此阶段,Nmap执行反向DNS查找以获取每个目标的主机名。-n跳过该阶段,-R强制对每个IP进行DNS反查,即便该IP不存活。默认只对online状态IP进行DNS反查。

端口扫描

Port scanning

default

-sn

在此阶段,Nmap确定端口的状态。可以使用-sn参数跳过它。

版本探测

Version detection

-sV

default

此阶段负责对打开的端口进行高级版本检测。仅在设置-sV参数时执行。

操作系统探测

OS detection

-O

default

在此阶段,Nmap会尝试确定目标的操作系统。仅在存在-O选项时执行。

跟踪路由

Trace route

--traceroute

default

在此阶段,Nmap执行到目标的跟踪路由。此阶段仅在设置了--traceroute选项时运行。

脚本扫描

Script scanning

default

default

在此阶段,脚本按照它们的执行规则运行。这里主要是portrule、hostrule和action(

输出

Output

default

 

在此阶段,Nmap格式化所有收集的信息,并以指定的格式将其返回给用户。

脚本扫描后期

Script post-scanning

default

default

在此阶段,只要设置--script或-sC就会执行。将评估具有postrule(post-scan execution rule)的NSE脚本,并给它们一个运行的机会。当然,在script中必须有postrule代码块才行。

 

这三个阶段只要强制执行脚本,没有下表中的绿色单元格(如果有rule函数,不执行rule函数,强制返回true)。

加载脚本

NSE: Loaded 1 scripts for scanning.

 

 

执行阶段

NSE: Script Pre-scanning.

NSE: Script scanning 10.100.1.100.

NSE: Script Post-scanning.

执行级别

NSE: Starting runlevel 1 (of 1) scan.

NSE: Starting runlevel 1 (of 1) scan.

NSE: Starting runlevel 1 (of 1) scan.

初始化

Initiating NSE at 19:44

Initiating NSE at 19:44

Initiating NSE at 19:44

Rule函数

NSE: [test2] =========prerule

NSE: [test2 10.100.1.100] =========hostrule

NSE: [test2] =========postrule

Action函数

NSE: Starting test2.

NSE: Starting test2 against 10.100.1.100.

NSE: Starting test2.

Action函数

=========action

=========action

=========action

完成Action

 

NSE: Finished test2 against 10.100.1.100.

 

Rule函数

 

NSE: [test2 10.100.1.100:80] =========portrule

 

Action函数

 

NSE: Starting test2 against 10.100.1.100:80.

 

Action函数

 

=========action

 

完成Action

NSE: Finished test2.

NSE: Finished test2 against 10.100.1.100:80.

NSE: Finished test2.

完成本阶段

Completed NSE at 19:44, 0.00s elapsed

Completed NSE at 19:44, 0.00s elapsed

Completed NSE at 19:44, 0.00s elapsed

 

Script Pre-scanning:默认阶段,prerule函数返回true则在此过程执行NSE脚本中的action函数,否则不执行,同时退出该扫描阶段。

Script scanning:默认阶段,没有action函数脚本报错。hostrule函数和portrule函数在该过程中首先被调用,如果它们返回true则继续执行action剩余代码,否则退出该过程。

Script Post-scanning:默认阶段,postrule函数返回true则在此过程执行NSE脚本中的action函数,否则不执行,同时退出该扫描阶段。

 

NSE脚本rules

NSE       scripts有4种不同类型的execution rule,不是说每个script都要有所有这4种:

prerule | postrule | hostrule | portrule

这些rule函数无需在NSE脚本的action函数中引用即可默认执行。

prerule 在Script pre-scanning阶段执行

hostrule、portrule在Script scanning阶段执行,先执行hostrule后执行portrule,portrule执行还需要开启Port scanning阶段才可以,否则被Skip掉。

postrule在Script post-scanning阶段执行

所有这些rule函数都必须返回boolean值: false  or  true

prerule()

以下是来自 targets-sniffer.nse NSE脚本的片段。它说明了我们如何使用 prerule 函数来检查Nmap是否以特权模式运行,以及它是否可以正确地确定网络接口:

prerule = function()

  return nmap.is_privileged() and

    (stdnse.get_script_args("targets-sniffer.iface") or nmap.get_interface())

end

hostrule()

sniffer-detect(检查本地局域网是否开启了混杂模式,这个脚本貌似有问题,没有检测出来)脚本的主机规则确定脚本仅对本地以太网Ipv4地址执行,也就是说只检查本地Ipv4局域网。不能是跨网段网络、不能是Ipv6网络:

hostrule = function(host)

  if nmap.address_family() ~= 'inet' then

    stdnse.debug1("is IPv4 compatible only.")

    return false

  end

  if host.directly_connected == true and

      host.mac_addr ~= nil and

      host.mac_addr_src ~= nil and

      host.interface ~= nil then

    local iface = nmap.get_interface_info(host.interface)

    if iface and iface.link == 'ethernet' then

      return true

    end

  end

  return false

end

portrule(host,       port)

oracle-sid-brute.nse脚本中,portrule去匹配服务检测字符串中是否包含1521端口或oracle-tns服务

portrule = shortport.port_or_service(1521, 'oracle-tns')

jdwp-inject.nse脚本中,portrule同样匹配服务检测字符串中是否有tcpwrapped服务,且是tcp协议、open状态,端口和协议没有被except。

portrule = function(host, port)

  return port.service == "tcpwrapped"

    and port.protocol == "tcp" and port.state == "open"

    and not(shortport.port_is_excluded(port.number,port.protocol))

end

postrule()

ssh- hostkey脚本使用 postrule 函数来检测共享相同SSH公钥的主机

postrule = function() return (nmap.registry.sshhostkey ~= nil) end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值