UDP port scanning with Scapy

Using Scapy, we can quickly develop an understanding of the underlying principles of UDP scanning. To positively confirm the existence of a UDP service on any given port, we will need to solicit a reply from that service. This can prove to be very difficult, as many UDP services will only reply to service-specific requests. Knowledge of any particular service can make it easier to positively identify that service; however, there are general techniques that can be used to determine, with a reasonable amount of accuracy, whether a service is running on a given UDP port. The technique that we will use with Scapy is to identify closed UDP ports with ICMP port-unreachable replies:

  1. To send a UDP request to any given port, we first need to build layers of that request. The first layer that we will need to construct is the IP layer:
  1. To build the IP layer of our request, we need to assign the IP object to the i variable. By calling the display() function, we can identify the attribute configurations of the object. By default, both the sending and receiving addresses are set to the loopback address, 127.0.0.1. These values can be modified by changing the destination address, by setting i.dst to be equal to the string value of the address we wish to scan. On calling the display() function again, we see that not only has the destination address been updated, but Scapy also automatically updates the source IP address to the address associated with the default interface. Now that we have constructed the IP layer of the request, we can proceed to the UDP layer:
  1. To build the UDP layer of our request, we use the same technique we used for the IP layer. In the example provided, the UDP object was assigned to the u variable. As mentioned previously, the default configurations can be identified by calling the display() function. Here, we can see that the default value for both the source and destination ports are listed as domain. As you might likely suspect, this is to indicate the DNS service associated with port the 53. DNS is a common service that can often be discovered on networked systems. To confirm this, one can call the value directly by referencing the variable name and attribute. This can then be modified by setting the attribute equal to the new port destination value, as follows:
  1. In the preceding example, the destination port is set to 123, which is the Network Time Protocol (NTP) port. Now that we have created both the IP and UDP layers, we need to construct the request by stacking these layers:
  1. We can stack the IP and UDP layers by separating the variables with a forward slash. These layers can then be set equal to a new variable that will represent the entire request. We can then call the display() function to view the configurations for the request. Once the request has been built, it can be passed to the sr1() function so that we can analyze the response:
  1. This same request can be performed without independently building and stacking each layer. Instead, we can use a single one-line command by calling the functions directly and passing them the appropriate arguments, as follows:
  1. Note that the response for these requests includes an ICMP packet that has the type field indicating that the host is unreachable and code field indicating that the port is unreachable. This response is commonly returned if the UDP port is closed. Now, we should attempt to modify the request so that it is sent to a destination port that corresponds to an actual service on the remote system. To do this, we change the destination port back to the port 53 and then send the request again, as follows:
  1. When the same request is sent to an actual service, no reply is received. This is because the DNS service running on the system's UDP port 53 will only respond to service-specific requests. Knowledge of this discrepancy can be used to scan for ICMP host-unreachable replies, and we can then identify potential services by flagging the non-responsive ports:
        #!/usr/bin/python

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *
import time
import sys

if len(sys.argv) != 4:
print "Usage - ./udp_scan.py [Target-IP] [First Port]
[Last Port]"
print "Example - ./upd_scan.py 10.0.0.5 1 100"
print "Example will UDP port scan ports 1 through
100 on 10.0.0.5"
sys.exit()
else:
ip = sys.argv[1]
start = int(sys.argv[2])
end = int(sys.argv[3])

for port in range(start,end):
ans = sr1(IP(dst=ip)/UDP(dport=port),timeout=5,verbose =0)
time.sleep(1)
if ans == None:
print port
else:
pass
  1. The provided Python script sends a UDP request to each of the first hundred ports in sequence. In case no response is received, the port is identified as being open. Make sure you modify the permissions of the file by running chmod 777 udp_scan.py. By running this script, we can identify all the ports that don't return an ICMP host-unreachable reply:
  1. A timeout of 5 seconds is used to adjust for latent responses that result from ICMP host-unreachable rate limiting. Even with this rather large response acceptance window, scanning in this fashion can still be unreliable at times. It is for this reason that UDP probing scans are often a more effective alternative.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset