Nmap 掃描報告BUG
1 UDP 3478狀態報表錯誤
以下實驗用於重現此問題:
在本地安裝了一台Windows XP2的虛擬機器,並開啟防火牆。在虛擬機器內使用netstat命令查看自己的連接埠狀態:
運行命令netstat -an,得到以下結果:
而同時,在本地PC機上使用Nmap6.00對該虛擬機器XP的UDP連接埠進行掃描。Nmap將會報告該虛擬機器的UDP 3478是開放的。虛擬機器IP為192.168.1.121,本地PC的IP為192.168.1.103。
2 Wireshark抓包與調試log
Nmap使用的掃描命令:
nmap -sU -sV -p 3478 -d3 --reason 192.168.1.121> F:/nmapudp3478.txt
在wireshark中,沒有看到來自目標機的任何UDP的回複包。而在log中可以看到在調試資訊行裡麵包含了“READ TIMEOUT”,讀取資訊逾時,所以,本質上Nmap並沒有從該UDP連接埠上讀取到任何資料。
3 根本原因分析
使用調試器跟蹤,逐步排查到問題所在,在指令檔stun.lua中有以下的函數:
-- Gets the server version ifit was returned by the server
-- @return status true onsuccess, false on failure
-- @return version stringcontaining the server product and version
getVersion = function(self)
-- check ifthe server version was cached
if (not(self.cache) or not(self.cache.version) ) then
self:getExternalAddress()
end
return true,(self.cache and self.cache.server or "")
end,
該函數用於擷取stun(3478連接埠對應的服務名字)伺服器的版本資訊。在每次進行stun服務掃描時都會調用到該函數。
在我們情境中,將目標機的防火牆開啟,在用Nmap進行連接埠掃描時,不會收到3478的UDP回複包,因而Nmap將3478的狀態設定為open|filtered(請參見nmap掃描原理部分);而在進行服務掃描階段,會對此類可能為開放的連接埠進行服務掃描,此時就會調用stun.lua指令碼中getVersion()函數。
此函數,若在目標機stun連接埠開放時,執行流程正確;而在stun連接埠沒有開放時,卻會產生錯誤。原因在於上述紅色程式碼中,僅嘗試擷取stun外部地址,並沒有判斷擷取的結果。而後續的返回行裡面,直接返回true(表示服務是開啟的)和server的版本資訊(可能為空白)。所以,即使對方stun連接埠根本沒有開啟,在此處也會被判斷為開啟。
4 解決方案
與stun.lua指令碼的作者Patrik討論了這個問題,他同意此處是一個BUG。
目前已經將代碼做了如下修改:
--Gets the server version if it was returned by the server
--@return status true on success, false on failure
--@return version string containing the server product and version
getVersion= function(self)
local status, response = false, nil
--check if the server version was cached
if( not(self.cache) or not(self.cache.version) ) then
local status, response = self:getExternalAddress()
if ( status ) then
return true,(self.cache and self.cache.server or "")
end
return false, response
end
return true, (self.cache and self.cache.server or "")
end,