Defeating Nmap Scans v0.1 v0.2
The well-known scanning tool Nmap allows users to discover running services on a target machine. In this tutorial, we use Haka to fool Nmap scans by crafting reset packets.
When launching a NULL (-sN), FIN (-sF) or XMAS (-sX) scan, Nmap forges a malicious packet with some flags activated. Nmap concludes that a port is closed on the target machine if it receives a RST packet.
Thanks to Haka API, we can forge RST packets and fool Nmap queries letting him think that all ports are closed on the target side. The following script starts by loading ipv4 and tcp dissectors. The next line disable the tcp-connection dissector to avoid Haka dropping all packets do not belonging to a valid connection. Finally, we define the secuity rule which will create a RST tcp packet if a nmap scanning packet is detected. In the last lines, we inject the newly crafted packet and drop the Nmap forged packet.
ipv4 = require('protocol/ipv4')
tcp = require('protocol/tcp')
haka.disable_dissector('tcp-connection')
haka.rule {
hooks = { 'tcp-up' },
eval = function(self, pkt)
local flags = pkt.flags.all
-- test for null, fin and xmas nmap scans
if flags == 0 or flags == 0x1 or flags == 0x29 then
-- raw packet
local rstpkt = haka.packet.new()
-- ip packet
rstpkt = ipv4.create(rstpkt)
rstpkt.ttl = pkt.ip.ttl
rstpkt.dst = pkt.ip.src
rstpkt.src = pkt.ip.dst
-- tcp packet
rstpkt = tcp.create(rstpkt)
rstpkt.srcport = pkt.dstport
rstpkt.dstport = pkt.srcport
rstpkt.flags.rst = true
rstpkt.flags.ack = true
rstpkt.ack_seq = pkt.seq + 1
-- inject forged packet and
-- drop malicious scanning packet
rstpkt:send()
pkt:drop()
end
end
}
Hearafter, a snippet output of a Nmap Xmas Scan ran on a server hosting multiple services:
root@kali:~# nmap -sX -P0 server
Starting Nmap 6.25 ( http://nmap.org ) at 2014-04-08 11:53 CEST
...
All 1000 scanned ports on server (192.168.20.1) are closed
Nmap done: 1 IP address (1 host up) scanned in 0.25 seconds
edit The above code has been updated to work on Haka 0.2 versions:
raw = require('protocol/raw')
ipv4 = require('protocol/ipv4')
tcp = require('protocol/tcp')
haka.rule {
hook = tcp.events.receive_packet,
eval = function(pkt)
local flags = pkt.flags.all
-- test for null, fin and xmas nmap scans
if flags == 0 or flags == 0x1 or flags == 0x29 then
-- raw packet
local rstpkt = raw.create()
-- ip packet
rstpkt = ipv4.create(rstpkt)
rstpkt.ttl = pkt.ip.ttl
rstpkt.dst = pkt.ip.src
rstpkt.src = pkt.ip.dst
-- tcp packet
rstpkt = tcp.create(rstpkt)
rstpkt.srcport = pkt.dstport
rstpkt.dstport = pkt.srcport
rstpkt.flags.rst = true
rstpkt.flags.ack = true
rstpkt.ack_seq = pkt.seq + 1
-- inject forged packet and
-- drop malicious scanning packet
rstpkt:send()
pkt:drop()
end
end
}