In my recent article about python and how to build a network scanner we discussed two possibilities for finding available hosts on the local network. The next step is to find open ports for a single host on the network.
This can be achieved by finding the open ports. This is called port scanning. Every service on a machine offers connections to clients by registering a port number at the local operating system. This port is then bound to this service (server process). A host can run multiple services and by checking all possible ports, we can find out which services are running on that host.
The following code block takes an IP address and a port number as input, checks whether the specified port is open and in the case of success the port number is returned.
def scanport(addr, port):
'''Check if port is open on host'''
socket_obj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
result = socket_obj.connect_ex((addr,port))
if result == 0:
machine_hostname = socket.gethostbyaddr(addr)
service = socket.getservbyport(port)
print "open port detected: " + str(addr) + " \t-- Port: " + str(port)
The python function which tries to establish a connection to this specific port takes an IP address and port as input and returns 0 in case of success and in case of failure an error indicator is returned:
result = socket_obj.connect_ex((addr,port))
This function is defined in the
socket library and is basically all we need for a port scanner. Now, we just need a loop which iterates over all ports we want to check, for every port we run
result = socket_obj.connect_ex((addr,port)) and check the result.
The code block shown above returns the open ports. Based on the IANA recommendation we then can assume which service is running behind the open port. This is useful for planning the next steps of penetration testing: finding the possible exploits for this service.
Because this is a widely used technique, administrators trend to swap the standard ports for service: When running a server - assuming the administration is done using ssh - and checking the ssh service logs, we notice that a lot of IP addresses are listed which tried to connect to the ssh service, usernames are well-chosen. The following is an exemption of a ssh auth log. It shows the source IP address and the username which tried to log into the server using ssh on port 22:
[code start:1lang:actionscript]Jul 10 15:32:43 Srv01 sshd: Failed password for root from 188.8.131.52 port 36292 ssh2
Jul 10 15:32:44 Srv01 sshd: Failed password for root from 184.108.40.206 port 36286 ssh2
Jul 10 15:32:45 Srv01 sshd: Failed password for root from 220.127.116.11 port 36301 ssh2
Jul 10 15:32:51 Srv01 sshd: Failed password for root from 18.104.22.168 port 36286 ssh2[/code]
Sysadmins know about these "attacks" and a common method to prevent attackers to recognize the ssh service is to bind another port for ssh and close port 22.
Now banner grabbing comes into the game. Banner grabbing is used to recognize a service for a port. Also, banner grabbing is quite simple: We try to connect to the open port, wait for a response from the service and display it. As you can see in the screenshot above, this method is quite effective. We recognized 5 open ports and banner grabbing reveals additional beneficial information, such as the name/kind of the server processes.
Banner grabbing with Python can be performed like this:
def bannergrabbing(addr, port):
'''Connect to process and return application banner'''
print "Gettig service information for port: ", port
bannergrabber = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
banner = bannergrabber.recv(100)
print banner, "\n"
print "Cannot connect to port ", port
An additional benefit of banner grabbing can be the detection of the server operating system. The defacto standard port scanner Nmap performs OS detection based on specific patterns. This is a great help but depending on the security mechanisms it may not be very accurate (see picture below). As you can see in the image above, banner grabbing on port 22 reveals not only that ssh is running on that port it also reveals the server operating system.
The following image shows the port scan results for another host using Nmap as the scanning engine and with OS recognition attempt enabled. The OS was detected correctly but the distribution and kernel revision is still unknown. In the picture above the server OS was revealed by using banner grabbing.