Menu
Home
Log in / Register
 
Home arrow Computer Science arrow Understanding Network Hacks
< Prev   CONTENTS   Next >

5.9 Port-Scan Detection

After writing some source code to scan for ports we now want to write a program to detect those scans. The program will need to remember all destination ports and the request time in Unix format (seconds since 1970/01/01) for every source IP. Then it will check if the number of requested ports is above the given maximum and treats the affair as a port-scan if it is.

The two variables nr_of_diff_ports and portscan_timespan define how many ports must be requested in how many seconds. If the amount is reached we iterate over all requested ports and delete the entries that don't fall into our timespan. If the source IP still reaches the number of necessary requested ports we print a message and all saved information will be deleted to avoid multiple alerts for a single scan.

1 #!/usr/bin/python

2

3 import sys

4 from time import time

5 from scapy.all import sniff

6

7 ip_to_ports = dict()

8

9 # Nr of ports in timespan seconds

10 nr_of_diff_ports = 10

11 portscan_timespan = 10

12

13

14 def detect_portscan(packet):

15 ip = packet.getlayer("IP")

16 tcp = packet.getlayer("TCP")

17

18 # Remember scanned port and time in unix format

19 ip_to_ports.setdefault(ip.src, {})

20 [str(tcp.dport)] = int(time())

21

22 # Source IP has scanned too much different ports?

23 if len(ip_to_ports[ip.src]) >= nr_of_diff_ports:

24 scanned_ports = ip_to_ports[ip.src].items()

25

26 # Check recorded time of each scan

27 for (scanned_port, scan_time) in scanned_ports:

28

29 # Scanned port not in timeout span? Delete it

30 if scan_time + portscan_timespan < int(time()):

31 del ip_to_ports[ip.src][scanned_port]

32

33 # Still too much scanned ports?

34 if len(ip_to_ports[ip.src]) >= nr_of_diff_ports:

35 print "Portscan detected from " + ip.src

36 print "Scanned ports " +

37 ",".join(ip_to_ports[ip.src].keys()) +

38 " "

39

40 del ip_to_ports[ip.src]

41

42 if len(sys.argv) < 2:

43 print sys.argv[0] + " <iface>"

44 sys.exit(0)

45

46 sniff(prn=detect_portscan,

47 filter="tcp",

48 iface=sys.argv[1],

49 store=0)

We filter only TCP traffic to keep the example as simple as possible. You should be able to extend the code for UDP scan detection without much effort.

Another extension possibility would be to not only log port-scans, but also block them. A simple possibility is to add a reject or drop rule to Iptables for the scanning source IP. Such a rule would look like the following:

os.system("iptables -A INPUT -s " + ip_to_ports[ip.src] + " -j DROP")

It should be remarked that this technique can be dangerous. A keen attacker could use IP spoofing to deny you access to a whole network or to just ban your DNS servers. Therefore you should also implement a whitelisting and a timeout mechanism to avoid blocking essential network resources like your default gateway. Another threat is if an attacker is able to inject any characters as source IP this can lead to a command injection attack (see Sect. 7.10). The input should be sanitized for characters interpreted by shells.

 
Found a mistake? Please highlight the word and press Shift + Enter  
< Prev   CONTENTS   Next >
 
Subjects
Accounting
Business & Finance
Communication
Computer Science
Economics
Education
Engineering
Environment
Geography
Health
History
Language & Literature
Law
Management
Marketing
Philosophy
Political science
Psychology
Religion
Sociology
Travel