Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Python for Security and Networking

You're reading from   Python for Security and Networking Leverage Python modules and tools in securing your network and applications

Arrow left icon
Product type Paperback
Published in Jun 2023
Publisher Packt
ISBN-13 9781837637553
Length 586 pages
Edition 3rd Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
José Manuel Ortega José Manuel Ortega
Author Profile Icon José Manuel Ortega
José Manuel Ortega
Arrow right icon
View More author details
Toc

Table of Contents (23) Chapters Close

Preface 1. Section 1: Python Environment and System Programming Tools
2. Working with Python Scripting FREE CHAPTER 3. System Programming Packages 4. Section 2: Network Scripting and Packet Sniffing with Python
5. Socket Programming 6. HTTP Programming and Web Authentication 7. Analyzing Network Traffic and Packet Sniffing 8. Section 3: Server Scripting and Port Scanning with Python
9. Gathering Information from Servers with OSINT Tools 10. Interacting with FTP, SFTP, and SSH Servers 11. Working with Nmap Scanner 12. Section 4: Server Vulnerabilities and Security in Web Applications
13. Interacting with Vulnerability Scanners 14. Interacting with Server Vulnerabilities in Web Applications 15. Obtain Information from Vulnerabilities Databases 16. Section 5: Python Forensics
17. Extracting Geolocation and Metadata from Documents, Images, and Browsers 18. Python Tools for Brute-Force Attacks 19. Cryptography and Code Obfuscation 20. Assessments – Answers to the End-of-Chapter Questions
21. Other Books You May Enjoy
22. Index

Learn about data structures and collections in Python

In this section, we will review different types of data structures, including lists, tuples, and dictionaries. We will see methods and operations for managing these data structures and practical examples where we review the main use cases.

Python lists

Lists in Python are equivalent to structures such as dynamic vectors in programming languages such as C and C++. We can express literals by enclosing their elements between a pair of brackets and separating them with commas. The first element of a list has index 0.

Lists in Python are, used to store sets of related items of the same or different types. Also, a list is a mutable data structure which allows the list content can be modified after it has been created.

To create a list in Python, simply enclose a comma-separated sequence of elements in square brackets []. For example, creating a list with response codes would be done as follows:

>>> responses = [200,400,403,500]

Indexes are used to access an element of a list. An index is an integer that indicates the position of an element in a list. The first element of a list always starts at index 0.

>>> responses[0]
200
>>> responses[1]
400

If an attempt is made to access an index that is outside the range of the list, the interpreter will throw the IndexError exception. Similarly, if an index that is not an integer is used, the TypeError exception will be thrown:

>>> responses[4]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Consider the following example: a programmer can create a list using the append() method by adding objects, printing the objects, and then sorting them before printing again. We describe a list of protocols in the following example, and use the key methods of a Python list, such as add, index, and remove:

>>> protocolList = []
>>> protocolList.append("FTP")
>>> protocolList.append("SSH")
>>> protocolList.append("SMTP")
>>> protocolList.append("HTTP")
>>> print(protocolList)
['FTP','SSH','SMTP','HTTP']
>>> protocolList.sort()
>>> print(protocolList)
['FTP','HTTP','SMTP','SSH']
>>> type(protocolList)
<type 'list'>
>>> len(protocolList)
4

To access specific positions, we can use the index() method, and to delete an element, we can use the remove() method:

>>> position = protocolList.index('SSH')
>>> print("SSH position"+str(position))
SSH position 3
>>> protocolList.remove("SSH")
>>> print(protocolList)
['FTP','HTTP','SMTP']
>>> count = len(protocolList)
>>> print("Protocol elements "+str(count))
Protocol elements 3

To print out the whole protocol list, use the following instructions. This will loop through all the elements and print them:

>>> for protocol in protocolList:
...     print(protocol)
...
FTP
HTTP
SMTP

Lists also provide methods that help manipulate the values within them and allow us to store more than one variable within them and provide a better way to sort object arrays in Python. These are the techniques commonly used to manage lists:

  • .append(value): Appends an element at the end of the list
  • .count('x'): Gets the number of 'x' elements in the list
  • .index('x'): Returns the index of 'x' in the list
  • .insert('y','x'): Inserts 'x' at location 'y'
  • .pop(): Returns the last element and removes it from the list
  • .remove('x'): Removes the first 'x' from the list
  • .reverse(): Reverses the elements in the list
  • .sort(): Sorts the list in ascending order

The indexing operator allows access to an element and is expressed syntactically by adding its index in brackets to the list, list [index]. You can change the value of a chosen element in the list using the index between brackets:

protocolList [4] = 'SSH'
print("New list content: ", protocols)

Also, you can copy the value of a specific position to another position in the list:

protocolList [1] = protocolList [4]
print("New list content:", protocols)

The value inside the brackets that selects one element of the list is called an index, while the operation of selecting an element from the list is known as indexing.

Adding elements to a list

Lists are mutable sequences that can be modified, which means items can be added, updated, or removed. To add one or more elements, we can use the extend() method. Also, we can use the insert() method to insert an element in a specific index location. We can add elements to a list by means of the following methods:

  • list.append(value): This method allows an element to be inserted at the end of the list. It takes its argument’s value and puts it at the end of the list that owns the method. The list’s length then increases by one.
  • list.extend(values): This method allows inserting many elements at the end of the list.
  • list.insert(location, value): The insert() method is a bit smarter since it can add a new element at any place in the list, not just at the end. It takes as arguments first the required location of the element to be inserted and then the element to be inserted.

In the following example we are using these methods to add elements to the response code list.

>>> responses.append(503)
>>> responses
[200, 400, 403, 500, 503]
>>> responses.extend([504,505])
>>> responses
[200, 400, 403, 500, 503, 504, 505]
>>> responses.insert(6,300)
>>> responses
[201, 400, 403, 500, 503, 504, 300, 505]

Reversing a list

Another interesting operation that we perform in lists is the one that offers the possibility of getting elements in a reverse way in the list through the reverse() method:

>>> protocolList.reverse()
>>> print(protocolList)
['SMTP','HTTP','FTP']

Another way to do the same operation is to use the -1 index. This quick and easy technique shows how you can access all the elements of a list in reverse order:

>>> protocolList[::-1]
>>> print(protocolList)
['SMTP','HTTP','FTP']

Searching elements in a list

In this example, we can see the code for finding the location of a given element inside a list. We use the range function to get elements inside protocolList and we compare each element with the element to find. When both elements are equal, we break the loop and return the element. To find out if an element is contained in a list, we can use the membership operator in.

>>> 'HTTPS' in protocolList
False
>>> 'HTTP' in protocolList
True

You can find the following code in the search_element_list.py file:

protocolList = ["FTP", "HTTP", "SNMP", "SSH"]
element_to_find = "SSH"
for i in range(len(protocolList)):
    if element_to_find in protocolList[i]:
        print("Element found at index", i)
        break

Now that you know how to add, reverse, and search for elements in a list, let’s move on to learning about tuples in Python.

Python tuples

Like lists, the tuple class in Python is a data structure that can store elements of different types.

Along with the list and range classes, it is one of the sequence types in Python, with the particularity that they are immutable. This means its content cannot be modified after it has been created.

In general, to create a tuple in Python, you simply define a sequence of elements separated by commas. Indices are used to access an element of a tuple. An index is an integer indicating the position of an element in a tuple. The first element of a tuple always starts at index 0.

>>> tuple=("FTP","SSH","HTTP","SNMP")
>>> tuple[0]
'FTP'

If an attempt is made to access an index that is outside the range of the tuple, the interpreter will throw the IndexError exception. Similarly, if an index that is not an integer is used, the TypeError exception will be thrown:

>>> tuple[5]
Traceback (most recent call last):
  File "<input>", line 1, in <module>
IndexError: tuple index out of range

As with lists and all sequential types, it is permissible to use negative indices to access the elements of a tuple. In this case, the index -1 refers to the last element of the sequence, -2 to the penultimate, and so on:

>>> tuple[-1]
'SNMP'
>>> tuple[-2]
'HTTP'

When trying to modify a tuple, we see how we get an error since tuples are immutable objects:

>>> tuple[0]="FTP"
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

Now that you know the basic data structures for working with Python, let’s move on to learning about Python dictionaries in order to organize information in the key-value format.

Python dictionaries

The Python dictionary data structure is probably the most important in the entire language and allows us to associate values with keys. Python’s dict class is a map type that maps keys to values. Unlike sequential types (list, tuple, range, or str), which are indexed by a numeric index, dictionaries are indexed by keys. Among the main features of the dictionaries, we can highlight:

  • It is a mutable type, that is, its content can be modified after it has been created.
  • It is a type that reserves the order in which key-value pairs are inserted.

In Python there are several ways to create a dictionary. The simplest is to enclose a sequence of comma-separated key:value pairs in curly braces {}. In this example we will define the service name as the key and the port number as the value.

>>> services = {"FTP":21, "SSH":22, "SMTP":25, "HTTP":80}

Another way to create a dictionary is using the dict class:

>>> dict(services)
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 80}
>>> type(services)
<class 'dict'>

Accessing an element of a dictionary is one of the main operations for which this type of data exists. Access to a value is done by indexing the key. To do this, simply enclose the key in square brackets. If the key does not exist, the KeyError exception will be thrown.

>>> services['FTP']
21

The dict class also offers the get (key[, default value]) method. This method returns the value corresponding to the key used as the first parameter. If the key does not exist, it does not throw any errors, but returns the second argument by default. If this argument is not supplied, the value None is returned.

>>> services.get('SSH')
22

If the key does not exist, it does not throw any errors, but returns the second argument by default.

>>> services.get('gopher', "service not found")
'service not found'

If this argument is not supplied, the value None is returned.

>>> type(services.get('gopher'))
<class 'NoneType'>

Using the update method, we can combine two distinct dictionaries into one. In addition, the update method will merge existing elements if they conflict:

>>> services = {"FTP":21, "SSH":22, "SMTP":25, "HTTP":80}
>>> services2 = {"FTP":21, "SSH":22, "SMTP":25, "LDAP":389}
>>> services.update(services2)
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 80, 'LDAP': 389}

The first value is the key, and the second the key value. We can use any unchangeable value as a key. We can use numbers, sequences, Booleans, or tuples, but not lists or dictionaries, since they are mutable.

The main difference between dictionaries and lists or tuples is that values contained in a dictionary are accessed by their name and not by their index. You may also use this operator to reassign values, as in the lists and tuples:

>>> services["HTTP"] = 8080
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 8080, 'LDAP': 389}

This means that a dictionary is a set of key-value pairs with the following conditions:

  • Each key must be unique: That means it is not possible to have more than one key of the same value.
  • A key may be a number or a string.
  • A dictionary is not a list: A list contains a set of numbered values, while a dictionary holds pairs of values.
  • The len() function: This works for dictionaries and returns the number of key-value elements in the dictionary.

IMPORTANT NOTE

In Python 3.10, dictionaries have become ordered collections by default.

The dict class implements three methods, since they return an iterable data type, known as view objects. These objects provide a view of the keys and values of type dict_values contained in the dictionary, and if the dictionary changes, these objects are instantly updated. The methods are as follows:

  • items(): Returns a view of (key, value) pairs from the dictionary.
  • keys(): Returns a view of the keys in the dictionary.
  • values(): Returns a view of the values in the dictionary.
>>> services.items()
dict_items([('FTP', 21), ('SSH', 22), ('SMTP', 25), ('HTTP', 8080), ('LDAP', 389)])
>>> services.keys()
dict_keys(['FTP', 'SSH', 'SMTP', 'HTTP', 'LDAP'])
>>> services.values()
dict_values([21, 22, 25, 8080, 389])

You might want to iterate over a dictionary and extract and display all the key-value pairs with a for loop:

>>> for key,value in services.items():
...     print(key,value)
... 
FTP 21
SSH 22
SMTP 25
HTTP 8080
LDAP 389

The dict class is mutable, so elements can be added, modified, and/or removed after an object of this type has been created. To add a new item to an existing dictionary, use the assignment operator =. To the left of the operator appears the dictionary object with the new key in square brackets [] and to the right the value associated with said key.

>>> services['HTTPS'] = 443
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 8080, 'LDAP': 389, 'HTTPS': 443}

Now that you know the main data structures for working with Python, let’s move on to learning how to structure our Python code with functions and classes.

Remove an item from a dictionary in Python

In Python there are several ways to remove an element from a dictionary. They are the following:

  • pop(key [, default value]): If the key is in the dictionary, it removes the element and return its value; if not, it returns the default value. If the default value is not provided and the key is not in the dictionary, the KeyError exception is raised.
  • popitem(): Removes the last key:value pair from the dictionary and returns it. If the dictionary is empty, the KeyError exception is raised.
  • del d[key]: Deletes the key:value pair. If the key does not exist, the KeyError exception is thrown.
  • clear(): Clears all key:value pairs from the dictionary.

In the following instructions we are removing the elements of the services dictionary using the previous methods:

>>> services = {'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 8080, 'LDAP': 389, 'HTTPS': 443} 
>>> services.pop('HTTPS')
443
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 8080, 'LDAP': 389}
>>> services.popitem()
('LDAP', 389)
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25, 'HTTP': 8080}
>>> del services['HTTP']
>>> services
{'FTP': 21, 'SSH': 22, 'SMTP': 25}
>>> services.clear()
>>> services
{}
You have been reading a chapter from
Python for Security and Networking - Third Edition
Published in: Jun 2023
Publisher: Packt
ISBN-13: 9781837637553
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image