mirror of
https://github.com/nmap/nmap.git
synced 2026-02-03 12:06:35 +00:00
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
129 lines
4.0 KiB
Lua
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
|