Penetration testing

Python for security professionals – Part 1

Harpreet Singh
November 27, 2017 by
Harpreet Singh

The Python language has many advantages when it comes to scripting. The power of python can be felt when you start working with and try new things with it. It has modules which can be used to create scripts to automate stuff, play with files and folders, Image processing, controlling keyboard and mouse, web scraping, regex parsing etc.

For those of you who are familiar with Kali Linux, many scripts are written in Python. There are many freeware tools which are there in the market which can get the job done, the why script it with Python? The answer to the question is simple. For those who have written the tools have a superset of requirements, they want to cover all the scenarios and add customisations to the tools. This ends up in tools getting complicated and cumbersome. Moreover, every time we do not have the feasibility to use tools and hence scripting comes handy. We can script tasks as per our need and requirement set.

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.

For security professionals, Python can be used for but not limited to:

  • Penetration testing
  • Information gathering
  • Scripting tools
  • Automating stuff
  • Forensics

I will be discussing a few examples where Python can be used along with the code and comments. I have tried to heavily comment the code so that it becomes easy to understand and digest. The approach which I have taken is to break the requirement into small steps and generate a flow control for how the code should go.

NOTE: I assume that the user is having basic knowledge of Python-like syntax, data types, flow control, loops, functions, sockets, etc. since the article will not be discussing the basics and will be drifting away from the conventional "hello world" approach.

Some prerequisites before baking the code

Python can be installed from https://www.python.org/downloads/

NOTE: In case you have not installed Python, I would recommend Python3, although Python3 is backward compatible with Python2 this might require some troubleshooting at times. Moreover, you can install both Python 2 and 3 at the same time in a system.

Module name: os

This module provides a way of using operating system dependent functionality with Python. It can be beneficial when working with files (opening, reading, writing), windows paths (both absolute and relative), folders (creating folders, finding size and folder contents), check path validity, running OS commands like clearing the cmd screen, etc.

Example 1: What's your name?

# Code

Import os

os.name

# Output for windows

'nt'

Example 2: Joining the paths

#Code

Import os

os.path.join('harpreet','py_scripts')

#Output

'harpreetpy_scripts'

Example 3: Where you are working right now?

#Code

Import os

os.getcwd()

#Output

'C:UsersharpreetsinghDesktop'

Example 4: Are you there or not?

# Checks the presence of a path/directory

#Code

Import os

os.chdir('C:UsersharpreetsinghDesktop')

Example 5: Creating folders/directories

#Code

Import os

os.makedirs('C:resourcesinfosecharpreetsingh')

Example 6: Running the window commands in Python

# Clearing the cmd inside Python screen

# Code

Import os

os.system('cls')

# Getting the IP address

os.system('ipconfig')

Example 7: Opening a file

# Steps involved:

  • Open
  • read /write
  • Close the file

# Step 1: Opening a file:

# Code

Import os

Myfile= open('C:UsersharpreetsinghDesktoptest.txt')

# Step 2(a): Reading contents of a file

Import os

Myfile=open('C:UsersharpreetsinghDesktoptext.txt')

Myfile.read()

# Step 2(b): Writing contents to a file

# Code

Import os

Myfile = open('C:UsersharpreetsinghDesktoptest.txt', 'w')

Myfile.write('I am written by Python in test file')

Myfile.close()

# Step 3: Closing the file

# Code

Import os

Myfile=open('C:UsersharpreetsinghDesktoptext.txt')

Myfile.close()

For further reading about os module:

Open cmd

Python

>>>import os

>>>help(os)

# Output

Module name: Webbrowser

This module is used to open link in the browser. We will be using the open function of this module to open links in the browser in the below examples. It can take two optional parameters '–n' to open URL in a new window or '-t' to open URL in new tab.

It will open the URL in the browser. In no time it will fire up the browser and open the link.

Example 1: Opening a URL in a web browser

# Code

Import webbrowser

webbrowser.open('https://google.com')

For further reading about web browser module

Open cmd

Python

>>>import webbrowser

>>>help(webbrowser)

# Output

Module name: Sys

With this module, command line arguments can be passed to the Python scripts

sys.argv[0] à name of the script

sys.argv[1] à argument passed by the user

Example 1: Printing the name of the script and user input

# Code

import sys

print ('n')

print "The name of the script is : %s" %sys.argv[0]

print ('n')

print "The input to the script is : %s" %sys.argv[1]

# Output

For further reading about sys module

Open cmd

Python

>>>import sys

>>>help(sys)

# Output

Module name: Urllib2

Urllib2 is used to fetch internet resources. We will be using this to fetch the response code for the URLs. It can even be used to download files, parse/fetch URL's, encode URLs, etc.

For further reading about urllib2 module

Open cmd

Python

>>>import urllib2

>>>help(urllib2)

# Output

Module Name: Socket

This module is used when we need to mix Python with networking. It can be used to create socket connections (TCP/UDP), binding the sockets to the host and port, closing the connection, promiscuous mode configurations and much more.

For further reading about socket module

Open cmd

Python

>>>import socket

>>>help(socket)

# Output

Ctypes:

It is a means of using C (low-level language) code within Python scripts. It will be used to decode the IP header in one of the below examples.

Data type - CTYPES

Date type - Python

C_bool <Boolean> Bool

C_char One character

C_byte <charcater> Int/long

C_ubyte <unsigned character> Int/long

C_shot <short> Int/long

C_ushort <unsigned short> Int/long

C_int <integer> Int/long

C_uint Int/long

C_long Int/long

C_ulong Int/long

C_float Float

For further reading about ctypes module

Open cmd

Python

>>>import ctypes

>>>help(ctypes)

# Output

IP packet architecture

  • Version: IP version used - 4 for IPv4 and 6 for IPv6.
  • IHL – IP Header Length: No of 32-bit words forming the header
  • Identification: a 16-bit number which is used to identify a packet uniquely.
  • Flags: Used to control fragment permissions for that packet.
  • TTL (Time to live): No of hops for which the packet may be routed. This number will get decremented by one each time the packet is routed through hops. This is used to avoid routing loops.
  • Protocol: This field helps us to identify the type of packet
    • 1 ICMP
    • 6 TCP
    • 17 UDP
  • Header Checksum: Used for error detection which might have been introduced during transit.
  • Source address: Source address from where the packet has originated
  • Destination address: Address for which the packet is destined for.

Let's code stuff

Bursting the directories

The below-discussed code will take two inputs – URL/IP address and the directory list which you would like to test. It will test for the existence of the directories and will open the URI in the browser if it exists.

Code Flow

Code and comments

""" *********** USAGE ****************

Create a file named dir.txt with the below data

/jmx-console

/images

/audio

/php-my-admin

/tag/sniffers/

Save the file dir.txt to a location and copy the location address (Replace the '' in the address with ''). Replace the address in the first line of the first for loop with this address.

Copy and paste the below code in an IDE and save it(dirb.py)

Command to run the code: python dirb.py (URL)

Example: python dirb.py sectools.org

"""

# Import required packages

import os,webbrowser,sys,urllib.request,urllib.error,urllib.parse

# Print the input of the user on the screen

print("The URL/IP entered is ")

print(str(sys.argv[1]))

print ("n")

url=str(sys.argv[1])

files=['dir.txt']

url_list=[]

for f in files:

hellow=open(os.path.join('C:UsersharpreetsinghDesktoppy_scripts', f))

directories = hellow.readlines()

# iterate through the directory list and create a list with directories appended to the IP/URL and save it

for i in directories:

i=i.strip()

url_list.append('http://'+url+i)

# Iterate through the items from the newly created list and check the response code

# Incase the response code is 200, open the link in the browser

for url in url_list:

print(url)

try:

connection = urllib.request.urlopen(url)

print(connection.getcode())

connection.close()

if connection.getcode() == 200:

webbrowser.open(url)

except urllib.error.HTTPError as e:

print(e.getcode())

# Output

# Response codes on the output screen

The program can be used to check for the existence of a directory or a set of directories for a URL. I was once assigned a task to check if the JMX-console was opened for 160 public IP addresses. Manually checking this would have been tedious and time-consuming. The list of directories can be downloaded from the internet or the same list as used by the DirBuster (tool in kali) can be used.

Packet capturing in windows

The script will capture the IP packet and will display the contents on the screen.

Code flow

Code and comments

""" ************* USAGE ********************

Copy and save the below code (capture.py)

Command to run the script: python capture.py

Change the IP address in the below code to that of yours.

Run the command prompt as admin as it is required for getting into promiscuous mode

"""

# Import the modules required

import socket,os

# Set the IP address of the host, change this to the IP address of your windows PC

IP = "192.168.0.105"

# define the socket protocol

socket_protocol = socket.IPPROTO_IP

# intitalize the socket

sniff = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket_protocol)

# Bind the socket to host IP and port

sniff.bind((IP,0))

# Include the IP headers HDRINCL (Header_Include)

sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# Turn on the promiscus mode

sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# Print what has been sniffed

print(sniff.recvfrom(65565))

# Turn of the promiscus mode

sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

# Output

The output is not human readable and needs to be decoded. Moreover, we have just captured a single packet which is not of much use.

Packet capturing and decoding

Here we will be capturing all the packets and will be decoding the contents of the header. We will decode and print protocol number, source address, and destination address.

Code and comments

""" ****************** USAGE *********************

Copy the below code and save it(decoder.py)

Command to run the script: python decoder.py

Change the IP address of the host in the below script to that of your's and run the command prompt as admin for promiscuous code permissions.

"""

#Import the required modules

import socket,os,struct

from ctypes import *

# Set the IP address of the host, check the IP address of your windows PC and replace it in tye below line of code

IP_of_host="192.168.0.105"

# use ctypes to map the ip header

class IP(Structure):

_fields_= [

("Version", c_ubyte, 4), # Version is of 4 bytes

("Ihl", c_ubyte, 4), # IHL is of 4 bytes

("TYPE_OF_SERVICE", c_ubyte, 8), # Type of service is of 8 bytes

("Total_Length", c_ushort, 16), # Total length is of 16 bytes

("Identification", c_ushort, 16), # Identification is of 16 bytes

("Fragment_offset", c_ushort, 16), # Fragment offset is of 16 bytes

("Time_to_live", c_ubyte, 8), # TTL is of 8 bytes

("Protocol_number", c_ubyte, 8), # Protocol Number is of 8 bytes

("Header_checksum", c_ushort, 16), # Header checksum is of 16 bytes

("Source_address", c_ulong, 32), # Source address is of 32 bytes

("Destination_address", c_ulong, 32) # Destination address is of 32 bytes

]

"""

If you add the above bytes, it sums up to 160 which when divided by 8 = 20, This confirms that the first 20 bytes of the packet are the IP headers. The size of the individual bits can be verified from IP packet architecture as well.

"""

def __new__(self, socket_buffer=None):

return self.from_buffer_copy(socket_buffer)

# getting the source address and destination address to what can be read by a normal person,

# We will be displaying the protocol Number, source address and destination address of the packets

# Rest can be ignored as of now.

# You can dig deeper into displaying other header fields if you like.

def __init__(self, socket_buffer=None):

self.src_address = socket.inet_ntoa(struct.pack("<L", self.Source_address))

self.dst_address = socket.inet_ntoa(struct.pack("<L", self.Destination_address))

self.protocol = str(self.Protocol_number)

# Specifying the socket protocol, Same as previous example

socket_protocol = socket.IPPROTO_IP

# Defining the socket

sniff = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket_protocol)

# Binding the socket to host IP and port and

sniff.bind((IP_of_host,0))

# We need the IP headers as well, IP_HDRINCL (Header_Include)

sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# Switch on the promiscus mode

sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

try:

# Starting the while loop with True so as to create an infinite loop to capture all packets continuously

while True:

raw_buffer = sniff.recvfrom(65565)[0]

# As we have discussed above that first 20 bytes are the IP header

ip_header = IP(raw_buffer[0:20])

# Printing the protocol number, Source address and destination address

print("Protocol %s %s --> %s" %(ip_header.protocol, ip_header.src_address, ip_header.dst_address))

# The interrupt will stop the always true while loop and turns off the promiscuous mode

except KeyboardInterrupt:

sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

FREE role-guided training plans

FREE role-guided training plans

Get 12 cybersecurity training plans — one for each of the most common roles requested by employers.

# Output

Run the script and open a website in a browser and you can see the packets getting captured. The packets can also be saved in a file by running the below command.

Python decoder.py > test.txt

The test.txt file can then be analyzed for later use.

Harpreet Singh
Harpreet Singh

Harpreet Singh is an Information Security enthusiast with 3 years of experience in different domains of Information security; namely, Identity and Access management, Risk and compliance, Information Protection and VAPT. He has been acknowledged and rewarded by Standard Chartered bank for outstanding performance and a leading payment solution firm for finding vulnerabilities in their online and local services. He is an author at cybrary.it [H5p] and has his own blog as well - harpreetsinghpassi@wordpress.com. Harpreet holds CEH v9 and many other online certifications. Loves to meet new people and always up for extempore, provide training sessions and pep talks. Apart from information security his areas of interest are - playing harmonica, surfing youtube and food reviewer [FoodBond_oo7@zomato].