Fork me on GitHub

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
}