nmap -- write a nmap script

目錄(?)[+]

漏洞掃描 --編寫Nmap腳本

200612月份,Nmap4.21 ALPHA1版加入腳本引擎,並將其作爲主線代碼的一部分。NSE腳本庫如今已經有400多個腳本,覆蓋了各種不同的網絡機制(SMB漏洞檢測到Stuxnet探測,及中間的一些內容)NSE的強大,依賴它強大的功能庫,這些庫可以非常容易的與主流的網絡服務和協議,進行交互。


挑戰

我們經常會掃描網絡環境中的主機是否存在某種新漏洞,而掃描器引擎中沒有新漏洞的檢測方法,這時候我們可能需要自己開發掃描工具。
你可能已經熟悉了某種腳本(例如:PythonPerletc.),並可以快速寫出檢測漏洞的程序。但是,如果面臨許多主機時, 針對兩三個主機的檢測方法,可能並不奏效。
Nmap 解救你 !使用內嵌的Lua語言和強大的集合庫,你可以結合nmap高效的主機和端口掃描引擎,開發出針對多數主機的檢測方法。

實現

Nmap 引擎腳本,由Lua編程語言、NmapAPI、系列強大的NSE庫實現。爲了達到本文的目的,現假設某個應用中存在一個叫ArcticFission漏洞。與許多其他的web應用程序類似,可以通過探測特定的文件,假設這個文件就是/arcticfission.html,用正則表達式提取文件內容中的版本號,與有漏洞的值進行對比.聽起來好像很簡單,讓我們開始吧!

框架代碼

基於傳統的語言標準,我們寫一個腳本,作用:遇到開放的HTTP端口,就返回”Hello World”
-- The Head Section --
-- The Rule Section --
portrule = function(host, port)
    return port.protocol == "tcp" and port.number == 80 and port.state == "open"
end

-- The Action Section --
action = function(host, port)
    return "Hello world !"
end
注意:--起始的行表示註釋。

NSE腳本主要由三部分組成:

The Head Section

該部分包含一些元數據,主要描述腳本的功能,作者,影響力,類別及其他。

The Rule Section

該部分定義腳本執行的必要條件。至少包含下面列表中的一個函數:
portrule
hostrule
prerule
postrule

此案例中,重點介紹portruleportrule能夠在執行操作前,檢查hostport屬性。portrule會利用nmapAPI檢查TCP80端口。

The Action Section

該部分定義腳本邏輯。此處案例中,檢測到開放80端口,則打印“HelloWorld”。腳本的輸出內容,會在nmap執行期間顯示出來。

root@security:/home/offensive/nmap_nse# nmap -sS -p 22,80,443 --script /home/offensive/nmap_nse/http-vuln-check.nse www.exploit-db.com

Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-29 10:39 EDT
Nmap scan report for www.exploit-db.com (192.99.12.218)
Host is up (0.47s latency).
Other addresses for www.exploit-db.com (not scanned): 198.58.102.135
rDNS record for 192.99.12.218: cloudproxy71.sucuri.net
PORT    STATE    SERVICE
22/tcp  filtered ssh
80/tcp  open     http
|_http-vuln-check: Hello world !
443/tcp open     https

調用腳本庫

優秀的庫集合,促使其變的強大。例如,可調用現有庫中的函數,針對http端口創建portrule。此處用到了shortport.

local shortport = require "shortport"

-- The Rule Section --
portrule = shortport.http

-- The Action Section --
action = function(host, port)
    return "Hello world!"
end

同樣的掃描,產生了不同的結果

root@security:/home/offensive/nmap_nse# nmap -sS -p 22,80,443 --script /home/offensive/nmap_nse/http-vuln-check_shortport.nse www.exploit-db.com

Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-29 10:36 EDT
Nmap scan report for www.exploit-db.com (192.99.12.218)
Host is up (0.46s latency).
Other addresses for www.exploit-db.com (not scanned): 198.58.102.135
rDNS record for 192.99.12.218: cloudproxy71.sucuri.net
PORT    STATE    SERVICE
22/tcp  filtered ssh
80/tcp  open     http
|_http-vuln-check_shortport: Hello world!
443/tcp open     https
|_http-vuln-check_shortport: Hello world!

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

該腳本對443執行了類似80端口的操作。主要是因爲shortport.http表示類似HTTP的端口(80,443,631,7080,8080,8088,5800,3872,8180,8000),也就是說,nmap會探測服務httphttpsipphttp-altvnc-httpoem-agentsoaphttp-proxy非標準端口,如果想要獲取更多的信息,請查閱shortport的文檔.


服務探測

讓我們把注意力放到action 部分的邏輯上。上述漏洞的檢測,首先需要探測頁面”/arcticfission.html”

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

-- The Rule Section --
portrule = shortport.http

-- The Action Section --
action = function(host, port)
    local uri = "/arcticfission.html"
    local response = http.get(host, port, uri)
    return response.status
end

上述代碼用到了庫http處理web頁面,

root@security:/home/offensive/nmap_nse# nmap -sS -p 22,80,443 --script /home/offensive/nmap_nse/http-vuln-check_shortport2.nse www.exploit-db.com

Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-29 11:16 EDT
Nmap scan report for www.exploit-db.com (192.99.12.218)
Host is up (0.48s latency).
Other addresses for www.exploit-db.com (not scanned): 198.58.102.135
rDNS record for 192.99.12.218: cloudproxy71.sucuri.net
PORT    STATE    SERVICE
22/tcp  filtered ssh
80/tcp  open     http
|_http-vuln-check_shortport2: 403
443/tcp open     https
|_http-vuln-check_shortport2: 400

上述輸出表明,兩個服務器端口不存在對應頁面”arcticfission.html”,注意'http'庫會自動在httphttps端口切換,因此你不需要考慮去實現TLS/SSL

如果只想輸出存在該頁面的web應用,可以如下操作:

local shortport = require "shortport"
local http = require "http"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
 
    local uri = "/arcticfission.html"
    local response = http.get(host, port, uri)
 
    if (response.status == 200) then
        return response.body
    end
end

上述代碼,返回狀態碼爲200的頁面內容。

注意:如果沒有數據返回或返回數據爲空,將導致無輸出顯示.


漏洞探測

許多時候,可以通過一個簡單的服務版本號,探測漏洞。這種情況,假象的服務器會返回一個包含版本號的標識。

local shortport = require "shortport"
local http = require "http"
local string = require "string"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
 
    local uri = "/arcticfission.html"
    local response = http.get(host, port, uri)
 
    if ( response.status == 200 ) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee][^>]*>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
        return title
    end
end

上述代碼,用到了string庫,以便獲取頁面頭。

offensive@security:~/nmap_nse$ nmap -p 80,443 --script /home/offensive/nmap_nse/http-vuln-check_shortport4.nse 192.168.1.105
 
Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-30 03:49 EDT
Nmap scan report for localhost (192.168.1.105)
Host is up (0.00053s latency).
PORT    STATE  SERVICE
80/tcp  open   http
|_http-vuln-check_shortport4: 1.0
443/tcp closed https
 
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

正如上面描述的那樣,現在需要將獲取的值與漏洞值比較, 確認是否存在漏洞。

local shortport = require "shortport"
local http = require "http"
local string = require "string"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
 
    local uri = "/arcticfission.html"
    local response = http.get(host, port, uri)
 
    if ( response.status == 200 ) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee][^>]*>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
 
        if ( title == "1.0" ) then
            return "Vnlnerable"
        else
            return "Not Vulnerable"
        end
    end
end

測試結果如下:

offensive@security:~/nmap_nse$ nmap -p 80,443 --script /home/offensive/nmap_nse/http-vuln-check_shortport5.nse 192.168.1.105
 
Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-30 04:05 EDT
Nmap scan report for localhost (192.168.1.105)
Host is up (0.00045s latency).
PORT    STATE  SERVICE
80/tcp  open   http
|_http-vuln-check_shortport5: Vnlnerable
443/tcp closed https

版本檢測的另一種方法,生成Hash與有漏洞的頁面對比。爲了實現此效果,此處調用了openssl庫。

local shortport = require "shortport"
local http = require "http"
local stdnse = require "stdnse"
local openssl = require "openssl"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
 
    local uri = "/arcticfission.html"
    local response = http.get(host, port, uri)
 
    if (response.status == 200) then
        local vulnsha1 = "398ffad678f17a4f16ccd00b1914ca986d0b9258"  
        local sha1 = string.lower(stdnse.tohex(openssl.sha1(response.body)))
 
        if ( sha1 == vulnsha1 ) then
            return "Vulnerable"
        else
            return "Not Vulnerable"
        end
    end
end

添加隱藏屬性

使用第三方的庫時,測試腳本的執行流程很重要。

offensive@security:~/nmap_nse$ nmap -p 80,443 --script /home/offensive/nmap_nse/http-vuln-check_openssl.nse --script-trace 192.168.1.105
 
Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-30 05:38 EDT
NSOCK INFO [0.0600s] nsi_new2(): nsi_new (IOD #1)
NSOCK INFO [0.0610s] nsock_connect_tcp(): TCP connection requested to 192.168.1.105:80 (IOD #1) EID 8
NSOCK INFO [0.0610s] nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [192.168.1.105:80]
NSE: TCP 192.168.1.106:59791 > 192.168.1.105:80 | CONNECT
NSE: TCP 192.168.1.106:59791 > 192.168.1.105:80 | 00000000: 47 45 54 20 2f 61 72 63 74 69 63 66 69 73 73 69 GET /arcticfissi
00000010: 6f 6e 2e 68 74 6d 6c 20 48 54 54 50 2f 31 2e 31 on.html HTTP/1.1
00000020: 0d 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c 68 6f 73   Host: localhos
00000030: 74 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 t  Connection: c
00000040: 6c 6f 73 65 0d 0a 55 73 65 72 2d 41 67 65 6e 74 lose  User-Agent
00000050: 3a 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 63 : Mozilla/5.0 (c
00000060: 6f 6d 70 61 74 69 62 6c 65 3b 20 4e 6d 61 70 20 ompatible; Nmap  
00000070: 53 63 72 69 70 74 69 6e 67 20 45 6e 67 69 6e 65 Scripting Engine
00000080: 3b 20 68 74 74 70 3a 2f 2f 6e 6d 61 70 2e 6f 72 ; http://nmap.or
00000090: 67 2f 62 6f 6f 6b 2f 6e 73 65 2e 68 74 6d 6c 29 g/book/nse.html)
000000a0: 0d 0a 0d 0a                                          
 
NSOCK INFO [0.0620s] nsock_trace_handler_callback(): Callback: WRITE SUCCESS for EID 19 [192.168.1.105:80]
NSE: TCP 192.168.1.106:59791 > 192.168.1.105:80 | SEND
NSOCK INFO [0.0620s] nsock_read(): Read request from IOD #1 [192.168.1.105:80] (timeout: 8000ms) EID 26
NSOCK INFO [0.0640s] nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 26 [192.168.1.105:80] (392 bytes)
NSE: TCP 192.168.1.106:59791 < 192.168.1.105:80 | 00000000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK  
00000010: 0a 44 61 74 65 3a 20 54 75 65 2c 20 33 30 20 53  Date: Tue, 30 S
00000020: 65 70 20 32 30 31 34 20 30 39 3a 33 38 3a 34 39 ep 2014 09:38:49
00000030: 20 47 4d 54 0d 0a 53 65 72 76 65 72 3a 20 41 70  GMT  Server: Ap
00000040: 61 63 68 65 2f 32 2e 32 2e 32 32 20 28 44 65 62 ache/2.2.22 (Deb
00000050: 69 61 6e 29 0d 0a 4c 61 73 74 2d 4d 6f 64 69 66 ian)  Last-Modif
00000060: 69 65 64 3a 20 54 75 65 2c 20 33 30 20 53 65 70 ied: Tue, 30 Sep
00000070: 20 32 30 31 34 20 30 37 3a 33 30 3a 33 33 20 47  2014 07:30:33 G
00000080: 4d 54 0d 0a 45 54 61 67 3a 20 22 65 31 31 38 31 MT  ETag: "e1181
00000090: 2d 37 34 2d 35 30 34 34 33 35 62 64 38 36 62 30 -74-504435bd86b0
000000a0: 32 22 0d 0a 41 63 63 65 70 74 2d 52 61 6e 67 65 2"  Accept-Range
000000b0: 73 3a 20 62 79 74 65 73 0d 0a 43 6f 6e 74 65 6e s: bytes  Conten
000000c0: 74 2d 4c 65 6e 67 74 68 3a 20 31 31 36 0d 0a 56 t-Length: 116  V
000000d0: 61 72 79 3a 20 41 63 63 65 70 74 2d 45 6e 63 6f ary: Accept-Enco
000000e0: 64 69 6e 67 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e ding  Connection
000000f0: 3a 20 63 6c 6f 73 65 0d 0a 43 6f 6e 74 65 6e 74 : close  Content
00000100: 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c -Type: text/html
00000110: 0d 0a 0d 0a 3c 68 74 6d 6c 3e 0a 3c 68 65 61 64     <html> <head
00000120: 3e 0a 3c 74 69 74 6c 65 3e 41 72 63 74 69 63 46 > <title>ArcticF
00000130: 69 73 73 69 6f 6e 20 31 2e 30 3c 2f 74 69 74 6c ission 1.0</titl
00000140: 65 3e 0a 3c 2f 68 65 61 64 3e 0a 3c 62 6f 64 79 e> </head> <body
00000150: 3e 0a 3c 68 31 3e 57 65 6c 63 6f 6d 65 20 74 6f > <h1>Welcome to
00000160: 20 41 72 63 74 69 63 46 69 73 73 69 6f 6e 20 31  ArcticFission 1
00000170: 2e 30 3c 2f 68 31 3e 0a 3c 2f 62 6f 64 79 3e 0a .0</h1> </body>  
00000180: 3c 2f 68 74 6d 6c 3e 0a                         </html>  
 
NSE: TCP 192.168.1.106:59791 > 192.168.1.105:80 | CLOSE
NSOCK INFO [0.0640s] nsi_delete(): nsi_delete (IOD #1)
Nmap scan report for localhost (192.168.1.105)
Host is up (0.00064s latency).
PORT    STATE  SERVICE
80/tcp  open   http
|_http-vuln-check_openssl: Vulnerable
443/tcp closed https
 
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

從上面的跟蹤看,NSE'http'庫使用的默認User-Agent是“Mozilla/5.0(compatible; Nmap Scripting Engine;http://nmap.org/book/nse.html)”. 可能由於某些安全原因,你需要更改user-agent,可使用下面方法.

offensive@security:~/nmap_nse$ nmap -p 80,443 --script /home/offensive/nmap_nse/http-vuln-check_openssl.nse --script-args="http.useragent='Mozilla/5.0 (compatible [offensive@security])'" --script-trace 192.168.1.105
 
Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-30 06:08 EDT
NSOCK INFO [0.2590s] nsi_new2(): nsi_new (IOD #1)
NSOCK INFO [0.2600s] nsock_connect_tcp(): TCP connection requested to 192.168.1.105:80 (IOD #1) EID 8
NSOCK INFO [0.2610s] nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [192.168.1.105:80]
NSE: TCP 192.168.1.106:59923 > 192.168.1.105:80 | CONNECT
NSE: TCP 192.168.1.106:59923 > 192.168.1.105:80 | 00000000: 47 45 54 20 2f 61 72 63 74 69 63 66 69 73 73 69 GET /arcticfissi
00000010: 6f 6e 2e 68 74 6d 6c 20 48 54 54 50 2f 31 2e 31 on.html HTTP/1.1
00000020: 0d 0a 48 6f 73 74 3a 20 31 39 32 2e 31 36 38 2e   Host: 192.168.
00000030: 31 2e 31 30 35 0d 0a 55 73 65 72 2d 41 67 65 6e 1.105  User-Agen
00000040: 74 3a 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 t: Mozilla/5.0 (
00000050: 63 6f 6d 70 61 74 69 62 6c 65 20 5b 6f 66 66 65 compatible [offe
00000060: 6e 73 69 76 65 40 73 65 63 75 72 69 74 79 5d 29 nsive@security])
00000070: 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c   Connection: cl
00000080: 6f 73 65 0d 0a 0d 0a                            ose     
 
NSOCK INFO [0.2610s] nsock_trace_handler_callback(): Callback: WRITE SUCCESS for EID 19 [192.168.1.105:80]
NSE: TCP 192.168.1.106:59923 > 192.168.1.105:80 | SEND
NSOCK INFO [0.2610s] nsock_read(): Read request from IOD #1 [192.168.1.105:80] (timeout: 8000ms) EID 26
NSOCK INFO [0.2640s] nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 26 [192.168.1.105:80] (392 bytes)
NSE: TCP 192.168.1.106:59923 < 192.168.1.105:80 | 00000000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK  
00000010: 0a 44 61 74 65 3a 20 54 75 65 2c 20 33 30 20 53  Date: Tue, 30 S
00000020: 65 70 20 32 30 31 34 20 31 30 3a 30 38 3a 32 34 ep 2014 10:08:24
00000030: 20 47 4d 54 0d 0a 53 65 72 76 65 72 3a 20 41 70  GMT  Server: Ap
00000040: 61 63 68 65 2f 32 2e 32 2e 32 32 20 28 44 65 62 ache/2.2.22 (Deb
00000050: 69 61 6e 29 0d 0a 4c 61 73 74 2d 4d 6f 64 69 66 ian)  Last-Modif
00000060: 69 65 64 3a 20 54 75 65 2c 20 33 30 20 53 65 70 ied: Tue, 30 Sep
00000070: 20 32 30 31 34 20 30 37 3a 33 30 3a 33 33 20 47  2014 07:30:33 G
00000080: 4d 54 0d 0a 45 54 61 67 3a 20 22 65 31 31 38 31 MT  ETag: "e1181
00000090: 2d 37 34 2d 35 30 34 34 33 35 62 64 38 36 62 30 -74-504435bd86b0
000000a0: 32 22 0d 0a 41 63 63 65 70 74 2d 52 61 6e 67 65 2"  Accept-Range
000000b0: 73 3a 20 62 79 74 65 73 0d 0a 43 6f 6e 74 65 6e s: bytes  Conten
000000c0: 74 2d 4c 65 6e 67 74 68 3a 20 31 31 36 0d 0a 56 t-Length: 116  V
000000d0: 61 72 79 3a 20 41 63 63 65 70 74 2d 45 6e 63 6f ary: Accept-Enco
000000e0: 64 69 6e 67 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e ding  Connection
000000f0: 3a 20 63 6c 6f 73 65 0d 0a 43 6f 6e 74 65 6e 74 : close  Content
00000100: 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c -Type: text/html
00000110: 0d 0a 0d 0a 3c 68 74 6d 6c 3e 0a 3c 68 65 61 64     <html> <head
00000120: 3e 0a 3c 74 69 74 6c 65 3e 41 72 63 74 69 63 46 > <title>ArcticF
00000130: 69 73 73 69 6f 6e 20 31 2e 30 3c 2f 74 69 74 6c ission 1.0</titl
00000140: 65 3e 0a 3c 2f 68 65 61 64 3e 0a 3c 62 6f 64 79 e> </head> <body
00000150: 3e 0a 3c 68 31 3e 57 65 6c 63 6f 6d 65 20 74 6f > <h1>Welcome to
00000160: 20 41 72 63 74 69 63 46 69 73 73 69 6f 6e 20 31  ArcticFission 1
00000170: 2e 30 3c 2f 68 31 3e 0a 3c 2f 62 6f 64 79 3e 0a .0</h1> </body>  
00000180: 3c 2f 68 74 6d 6c 3e 0a                         </html>  
 
NSE: TCP 192.168.1.106:59923 > 192.168.1.105:80 | CLOSE
NSOCK INFO [0.2660s] nsi_delete(): nsi_delete (IOD #1)
Nmap scan report for 192.168.1.105
Host is up (0.00053s latency).
PORT    STATE  SERVICE
80/tcp  open   http
|_http-vuln-check_openssl: Vulnerable
443/tcp closed https
 
Nmap done: 1 IP address (1 host up) scanned in 0.27 seconds

local shortport = require "shortport"
local http = require "http"
local stdnse = require "stdnse"
local string = require "string"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
     
    local uri = "/arcticfission.html"
     
    local options = {headers={}}
    options['headers']['User-Agent'] = "Mozilla/5.0 (compatible; ArcticFission)"
     
    local response = http.get(host, port, uri, options)
 
    if ( response.status == 200 ) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee][^>]*>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
 
        if ( title == "1.0" ) then
            return "Vulnerable"
        else
            return "Not Vulnerable"
        end
    end    
end

包裝腳本

如果你想要發佈腳本,有些重要的元數據需要提供,例如:描述、作者信息、證書,以便理解腳本的功能與影響力.

-- The Head Section --
description = [[Sample script to detect a fictional vulnerability in a fictional ArcticFission 1.0 web server]]
author = "iphelix"
license = "Same as Nmap -- See http://nmap.org/book/man-legal.html"
categories = {"default", "safe"}
 
local shortport = require "shortport"
local http = require "http"
local stdnse = require "stdnse"
local string = require "string"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
    local uri = "/arcticfission.html"
    local options = {header={}}
    options['header']['User-Agent'] = "Mozilla/5.0 (compatible; ArcticFission)"
 
    local response = http.get(host, port, uri, options)
 
    if ( response.status == 200) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee]>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
 
        if ( title == "1.0" ) then
            return "Vulnerable"
        else
            return "Not Vulnerable"
        end
    end
end

你現在可能想寫入一些NSE文檔格式的說明。腳本文檔可能包含一些可能會被文檔系統處理的特殊標識。(例如@output表示腳本輸出,@args表示腳本參數,@usage表示簡單的命令行參數,等)

-- The Head Section --
description = [[Sample script to detect a fictional vulnerability in a fictional ArcticFission 1.0 web server]]
 
---
-- @usage
-- nmap --script http-vuln-check <target>
-- @output
-- PORT    STATE  SERVICE
-- 80/tcp  open   http
-- |_http-vuln-check_packaging: Vulnerable
 
 
author = "iphelix"
license = "Same as Nmap -- See http://nmap.org/book/man-legal.html"
categories = {"default", "safe"}
 
local shortport = require "shortport"
local http = require "http"
local stdnse = require "stdnse"
local string = require "string"
 
-- The Rule Section --
portrule = shortport.http
 
-- The Action Section --
action = function(host, port)
    local uri = "/arcticfission.html"
    local options = {header={}}
    options['header']['User-Agent'] = "Mozilla/5.0 (compatible; ArcticFission)"
 
    local response = http.get(host, port, uri, options)
 
    if ( response.status == 200) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee]>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
 
        if ( title == "1.0" ) then
            return "Vulnerable"
        else
            return "Not Vulnerable"
        end
    end
end

解析輸出

使用自定義的腳本檢測完成後,我們還需要解析產生的結果,以易理解的方式輸出報告。不幸的是,'gnamp'輸出格式不支持腳本輸出,所以我們選擇解析'xml'格式的輸出。

#!/usr/bin/env python
# nmap-xml-parse by iphelix
 
import sys
from xml.dom.minidom import parse
 
 
def main():
    if len(sys.argv) != 2:
        print "Usage: %s nmap_output.xml" % sys.argv[0]
        sys.exit(1)
 
    nmap = parse(sys.argv[1])
 
    for host in nmap.getElementsByTagName("host"):
        addresses = [addr.getAttribute("addr")
                     for addr in host.getElementsByTagName("address")]
 
        for port in host.getElementsByTagName("port"):
            portid = port.getAttribute("portid")
 
            for script in port.getElementsByTagName("script"):
                if script.getAttribute("id") == "http-vuln-check_packaging":
                    output = script.getAttribute("output")
 
                    for address in addresses:
                        print "%s,%s,%s" % (address, portid, output)
 
if __name__ == "__main__":
    main()

漏洞管理

上述漏洞發現腳本有些問題。首先,它沒有漏洞相關的描述信息,其次,完成掃描後,你需要編寫腳本解析整個掃描結果。上面的這些,可以用Nmap的庫'vulns'進行處理。


NSE漏洞庫

NSE漏洞庫DjalalHarouniHenriDoreau開發,目的是標準化呈現與管理漏洞。

-- The Head Section --
description = [[Sample script to detect a fictional vulnerability in a fictional ArcticFission 1.0 web server]]
 
---
-- @usage
-- nmap --script http-vuln-check <target>
-- @output
-- PORT    STATE  SERVICE
-- 80/tcp  open   http
-- |_http-vuln-check_packaging: Vulnerable
-- |   VULNERABLE
-- |   ArcticFission 1.0 Vulnerability
-- |     State: VULNERABLE
-- |     IDs: CVE:CVE-XXXX-XX
-- |     References:
-- |_      http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-XXXX-XX
 
 
 
author = "iphelix"
license = "Same as Nmap -- See http://nmap.org/book/man-legal.html"
categories = {"default", "safe"}
 
local shortport = require "shortport"
local http = require "http"
local stdnse = require "stdnse"
local string = require "string"
local vulns = require "vulns"
 
 
-- The Rule Section --
portrule = shortport.http 
-- The Action Section --
action = function(host, port)
 
    -- The Vuln Definition Section --
    local vuln = {
        title = "ArcticFission 1.0 Vulnerability",
        state = vulns.STATE.NOT_VULN,
        IDS = { CVE = 'CVE-XXXX-XXX' }
    }
    local report = vulns.Report:new(SCRIPT_NAME, host, port)
 
    local uri = "/arcticfission.html"
    local options = {header={}}
    options['header']['User-Agent'] = "Mozilla/5.0 (compatible; ArcticFission)"
 
    local response = http.get(host, port, uri, options)
 
    if ( response.status == 200) then
        local title = string.match(response.body, "<[Tt][Ii][Tt][Ll][Ee]>ArcticFission ([^<]*)</[Tt][Ii][Tt][Ll][Ee]>")
 
        if ( title == "1.0" ) then
            vuln.state = vulns.STATE.VULN
        else
            vuln.state = vulns.STATE.NOT_VULN
        end
    end
 
    return report:make_output(vuln)
end

掃描結果如下:

offensive@security:~/nmap_nse$ nmap -p 80,443 --script /home/offensive/nmap_nse/http-vuln-check_packaging.nse  192.168.1.105
 
Starting Nmap 6.47 ( http://nmap.org ) at 2014-09-30 10:22 EDT
Nmap scan report for localhost (192.168.1.105)
Host is up (0.00053s latency).
PORT    STATE  SERVICE
80/tcp  open   http
| http-vuln-check_packaging:  
|   VULNERABLE:
|   ArcticFission 1.0 Vulnerability
|     State: VULNERABLE
|     IDs:  CVE:CVE-XXXX-XXX
|     References:
|_      http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-XXXX-XXX
443/tcp closed https
 
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

從這裏獲取了什麼

我希望你能夠對上面我提到的Nmap腳本感到興奮。最好的辦法就是學習庫相關的文檔,並編寫一些複雜的腳本,不侷限於httpNmap是一款強大的工具,強大的腳本庫及開源的社區支持,會促使其變成一款強大的漏洞掃描器。感謝,Fyodor和所有的Nmap開發者。


參考鏈接

NmapNetwork Scanning

Lua

NmapAPI

NSELibraries

pwnmaps

NSEVulnerability Library

ListTCP and UDP port

[原始鏈接]writingnse scripts for vulnerability scanning

發佈了151 篇原創文章 · 獲贊 30 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章