How to do it...

Let's use Scapy to perform firewall identification:

  1. To effectively determine whether a TCP port is filtered or not, both a TCP SYN packet and a TCP ACK packet need to be sent to the destination port. Based on the packets that are returned in response to these injections, we can determine whether the ports are filtered. Most likely, the injection of these two packets will result in one of the four different combinations of responses. We will discuss each of these scenarios, what they indicate about filtering associated with the destination port, and how to test for each. These four possible combinations of responses include the following:
    • SYN solicits no response, and ACK solicits an RST response
    • SYN solicits a SYN+ACK or SYN+RST response, and ACK solicits no response
    • SYN solicits a SYN+ACK or SYN+RST response, and ACK solicits an RST response
    • SYN solicits no response and ACK solicits no response
  2. In the first scenario, we should consider a configuration in which an injected SYN packet solicits no response and an ACK packet solicits an RST response. To test this, we should first send a TCP ACK packet to the destination port. To send the TCP ACK packet to any given port, we must first build the layers of the request. The first layer we will need to construct is the IP layer:
  1. To build the IP layer of our request, we should assign the IP object to the i variable. By calling the display() function, we can identify the attribute configurations for the object. By default, both the sending and receiving addresses are set to the 127.0.0.1 loopback address. These values can be modified by changing the destination address, setting i.dst equal to the string value of the address we wish to scan.
  1. By calling the display() function again, we can see that not only has the destination address been updated, but Scapy will also automatically update the source IP address to the address associated with the default interface. Now that we have constructed the IP layer of the request, we should proceed to the TCP layer:
  1. To build the TCP layer of our request, we will use the same technique we used for the IP layer. In the example provided, the TCP object was assigned to the t variable. As discussed previously, the default configurations can be identified by calling the display() function. Here, we can see that the default value for the source port is set to the port 21 (FTP), and the default value of the destination port is set to the port 80 (HTTP).
  1. The destination port value can be modified by setting it equal to the new port destination value, and the flags value should be set to A to indicate that the ACK flag bit should be activated. Now that we have created both the IP and TCP layers, we need to construct the request by stacking those layers:
  1. The IP and TCP layers can be stacked by separating the variables with a forward slash. These layers can then be set as equal to a new variable that will represent the entire request. The display() function can then be called to view the configurations for the request. Once the request has been built, this can then 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, a single one-line command can be used by calling the functions directly and passing the appropriate arguments to them:
  1. Notice that in this particular scenario, an RST packet is received in response to the injected ACK packet. The next step in testing is to inject a SYN packet in the same manner:
  1. Upon sending the SYN request in the same manner, no response is received and the function is discontinued when the timeout value is exceeded. This combination of responses indicates that stateful filtering is in place. The socket is rejecting all inbound connections by dropping SYN requests, but ACK packets are not filtered to ensure that outbound connections and sustained communication remains possible. This combination of responses can be tested in Python to identify statefully filtered ports:
  1. After formulating each of the requests with Scapy, the test that can be used to evaluate these responses determines whether a response is received from either the ACK or the SYN injection, but not both. This test is effective for identifying both this scenario and the next scenario in which a reply will be received from the SYN injection but not the ACK injection. A scenario in which a SYN+ACK or RST+ACK response is solicited by the SYN injection, but no response is solicited from the ACK injection, is also an indication of stateful filtering. The testing for this remains the same.

First, an ACK packet should be sent to the destination port:

  1. Notice that in the example provided, no response is solicited by this injection. Alternatively, if a SYN packet is injected, a response is received with the SYN+ACK flag bits activated if the port is open and the RST+ACK flag bits activated if the port is closed:
  1. The exact same test can be performed in the event of this scenario, since the test identifies that stateful filtering is in place by determining whether one of the two injections solicits a response, but not both:
  1. This combination of responses indicates that stateful filtering is being performed on ACK packets, and any ACK packets sent outside the context of a proper session are dropped. However, the port is not totally filtered, as evidenced by the responses to the inbound connection attempt. Another possible scenario would be if both the SYN and ACK injections solicited their expected responses. In such a scenario, there is no indication of any sort of filtering. To perform the testing for this scenario, an ACK injection should be performed and the response should be analyzed:
  1. In the event that the port is unfiltered, an unsolicited ACK packet sent to the destination port should result in a returned RST packet. This RST packet indicates that the ACK packet was sent out of context and is intended to discontinue the communication. Upon sending the ACK injection, a SYN injection should also be sent to the same port:
  1. In the event that the port is unfiltered and is open, a SYN+ACK response will be returned. Notice that the actual value of the TCP flags attribute is a long variable with the value of 18. This value can easily be converted to an integer using the int function. This value of 18 is the decimal value of the TCP flag bit sequence. The SYN flag bit carries a decimal value of 2, and the ACK flag bit carries a decimal value of 16. Assuming there is no indication of stateful filtering, we can test in Python whether the port is unfiltered and open by evaluating the integer conversion of the TCP flags value:
  1. A similar test can be performed to determine whether a port is unfiltered and closed. An unfiltered closed port will have the RST and ACK flag bits activated. As discussed previously, the ACK flag bit carries a decimal value of 16, and the RST flag bit carries a decimal value of 4. So, the expected integer conversion of the TCP flags value for an unfiltered and closed port should be 20:
  1. Finally, we should consider a scenario in which no response is received from the SYN or ACK injections. In this scenario, both instances of the sr1() function will be discontinued when the supplied timeout value is exceeded:
  1. This lack of response from either of the injections is likely an indication that the port is unstatefully filtered and is just dropping all incoming traffic regardless of the state, or it could be an indication that the remote host is down. One's first thought might be that this could be tested for in Python by appending an execution flow for else at the end of the previously developed testing sequence. This else operation would, in theory, be executed if a response were not received by one or both injections. In short, the else operation would be executed if no response were received:
  1. While this may seem like it would work in theory; it is less effective in practice. Python will actually return an error if value testing is performed on a variable that has no value. To avoid this problem, the first conditional that should be examined will be whether or not any reply is received at all:
  1. This entire sequence of testing can then be integrated into a single functional script. The script will accept two arguments to include the destination IP address and the port to be tested. An ACK and SYN packet will then be injected and the responses, if any, will be stored for evaluation.
  1. Then, a series of four tests will be performed to determine whether filtering exists on the port. Initially, a test will be performed to determine whether any response is received at all. If no response is received, the output will indicate that the remote host is down or the port is unstatefully filtered and discarding all traffic. If any response is received, a test will be performed to determine whether it was a response to one injection but not both. If such is the case, the output will indicate that the port is statefully filtered.
  2. Finally, if responses are received from both injections, the port will be identified as unfiltered, and the TCP flags value will be assessed to determine whether the port is open or closed:
        #!/usr/bin/python

import sys
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *

if len(sys.argv) != 3:
print "Usage - ./ACK_FW_detect.py [Target-IP]
[Target Port]"
print "Example - ./ACK_FW_detect.py 10.0.0.5 443"
print "Example will determine if filtering exists
on port 443 of host 10.0.0.5"
sys.exit()

ip = sys.argv[1]
port = int(sys.argv[2])

ACK_response =
sr1(IP(dst=ip)/TCP(dport=port,flags='A'),timeout=1,verbose=0)
SYN_response =
sr1(IP(dst=ip)/TCP(dport=port,flags='S'),timeout=1,verbose=0)
if (ACK_response == None) and (SYN_response == None):
print "Port is either unstatefully filtered or
host is down"
elif ((ACK_response == None) or (SYN_response == None))
and not
((ACK_response == None) and (SYN_response == None)):
print "Stateful filtering in place"
elif int(SYN_response[TCP].flags) == 18:
print "Port is unfiltered and open"
elif int(SYN_response[TCP].flags) == 20:
print "Port is unfiltered and closed"
else:
print "Unable to determine if the port is filtered"
  1. Upon creating the script in the local filesystem, the file permissions will need to be updated to allow execution of the script. The chmod command can be used to update these permissions, and the script can then be executed by calling it directly and passing the expected arguments to it:
..................Content has been hidden....................

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