實驗簡述
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中如何使用腳本以及腳本的編寫,通過學習編寫了簡單的測試腳本。