1
0
mirror of https://github.com/nmap/nmap.git synced 2026-02-03 12:06:35 +00:00
Files
nmap/scripts/sniffer-detect.nse
batrick de4ba536de Merge from /nmap-exp/patrick/nse-nsock-maintenance.
This is a maintenance fix for the NSE Nsock library binding. The patch focuses
on code correctness and simplicity. The patch also brings some initial updates
with an eye towards the upcoming Lua 5.2 release. See [1] for a post concerning
this branch.

[1] http://seclists.org/nmap-dev/2010/q3/710
2010-09-18 20:35:09 +00:00

129 lines
4.0 KiB
Lua

description = [[
Checks if a target on a local Ethernet has its network card in promiscuous mode.
The techniques used are described at
http://www.securityfriday.com/promiscuous_detection_01.pdf.
]]
---
-- @output
-- Host script results:
-- |_ sniffer-detect: Likely in promiscuous mode (tests: "11111111")
author = "Marek Majkowski"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery", "intrusive"}
-- okay, we're interested only in hosts that are on our ethernet lan
hostrule = function(host)
return host.directly_connected == true and
host.mac_addr ~= nil and
host.mac_addr_src ~= nil and
host.interface ~= nil and
nmap.get_interface_link(host.interface) == 'ethernet'
end
local function check (packetsz, layer2, layer3)
return string.sub(layer2, 0, 12)
end
do_test = function(dnet, pcap, host, test)
local status, length, layer2, layer3
local i = 0
-- ARP requests are send with timeouts: 10ms, 40ms, 90ms
-- before each try, we wait at least 100ms
-- in summary, this test takes at least 100ms and at most 440ms
for i=1,3 do
-- flush buffers :), wait quite long.
repeat
pcap:set_timeout(100)
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(length, layer2, layer3) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
until status ~= true
pcap:set_timeout(10 * i*i)
dnet:ethernet_send(test)
local test = host.mac_addr_src .. host.mac_addr
status, length, layer2, layer3 = pcap:pcap_receive()
while status and test ~= check(length, layer2, layer3) do
status, length, layer2, layer3 = pcap:pcap_receive()
end
if status == true then
-- the basic idea, was to inform user about time, when we got packet
-- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms)
-- but when we're running this tests on macs, first test is always 2.
-- which means that the first answer is dropped.
-- for now, just return 1 if test was successfull, it's easier
-- return(i)
return(1)
end
end
return('_')
end
action = function(host)
local dnet = nmap.new_dnet()
local pcap = nmap.new_socket()
local _
local status
local results = {
['1_____1_'] = false, -- MacOSX(Tiger.Panther)/Linux/ ?Win98/ WinXP sp2(no pcap)
['1_______'] = false, -- Old Apple/SunOS/3Com
['1___1_1_'] = false, -- MacOSX(Tiger)
['11111111'] = true, -- BSD/Linux/OSX/ (or not promiscous openwrt )
['1_1___1_'] = false, -- WinXP sp2 + pcap|| win98 sniff || win2k sniff (see below)
['111___1_'] = true, -- WinXP sp2 promisc
-- ['1111__1_'] = true, -- ?Win98 promisc + ??win98 no promisc *not confirmed*
}
dnet:ethernet_open(host.interface)
pcap:pcap_open(host.interface, 64, false, "arp")
local test_static = host.mac_addr_src ..
string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) ..
host.mac_addr_src ..
host.bin_ip_src ..
string.char(0x00,0x00, 0x00,0x00, 0x00,0x00) ..
host.bin_ip
local t = {
string.char(0xff,0xff, 0xff,0xff, 0xff,0xff), -- B32 no meaning?
string.char(0xff,0xff, 0xff,0xff, 0xff,0xfe), -- B31
string.char(0xff,0xff, 0x00,0x00, 0x00,0x00), -- B16
string.char(0xff,0x00, 0x00,0x00, 0x00,0x00), -- B8
string.char(0x01,0x00, 0x00,0x00, 0x00,0x00), -- G
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x00), -- M0
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x01), -- M1 no meaning?
string.char(0x01,0x00, 0x5e,0x00, 0x00,0x03), -- M3
}
local v
local out = ""
for _, v in ipairs(t) do
out = out .. do_test(dnet, pcap, host, v .. test_static)
end
dnet:ethernet_close()
pcap:pcap_close()
if out == '1_1___1_' then
return 'Windows with libpcap installed; may or may not be sniffing (tests: "' .. out .. '")'
end
if results[out] == false then
-- probably not sniffing
return
end
if results[out] == true then
-- rather sniffer.
return 'Likely in promiscuous mode (tests: "' .. out .. '")'
end
-- results[out] == nil
return 'Unknown (tests: "' .. out .. '")'
end