Book Image

Mastering Python for Networking and Security - Second Edition

By : José Ortega
Book Image

Mastering Python for Networking and Security - Second Edition

By: José Ortega

Overview of this book

It’s now more apparent than ever that security is a critical aspect of IT infrastructure, and that devastating data breaches can occur from simple network line hacks. As shown in this book, combining the latest version of Python with an increased focus on network security can help you to level up your defenses against cyber attacks and cyber threats. Python is being used for increasingly advanced tasks, with the latest update introducing new libraries and packages featured in the Python 3.7.4 recommended version. Moreover, most scripts are compatible with the latest versions of Python and can also be executed in a virtual environment. This book will guide you through using these updated packages to build a secure network with the help of Python scripting. You’ll cover a range of topics, from building a network to the procedures you need to follow to secure it. Starting by exploring different packages and libraries, you’ll learn about various ways to build a network and connect with the Tor network through Python scripting. You will also learn how to assess a network's vulnerabilities using Python security scripting. Later, you’ll learn how to achieve endpoint protection by leveraging Python packages, along with writing forensic scripts. By the end of this Python book, you’ll be able to use Python to build secure apps using cryptography and steganography techniques.
Table of Contents (22 chapters)
1
Section 1: The Python Environment and System Programming Tools
4
Section 2: Network Scripting and Extracting Information from the Tor Network with Python
8
Section 3: Server Scripting and Port Scanning with Python
12
Section 4: Server Vulnerabilities and Security in Python Modules
16
Section 5: Python Forensics

Python modules and packages

In this section, you will learn how Python provides modules that are built in a modular way and offers the possibility to developers to create their own modules.

What is a module in Python?

A module is a collection of functions, classes, and variables that we can use from a program. There is a large collection of modules available with the standard Python distribution.

A module can be specified as a file containing definitions and declarations from Python. The filename is the module name attached with the .py suffix. We can start by defining a simple module in a .py file. We’ll define a simple test() function inside this my module.py file that will print “This is my first module”:

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

def test():
print(“This is my first module”)

Within our main.py file, we can then import this file as a module and use our newly-defined test() method, like so:

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

import my_module
def main():
my_module.test()
if __name__ == ‘__main__’:
main()

When a module is imported, its content is implicitly executed by Python. It gives the module the chance to initialize some of its internal aspects. The initialization takes place only once, when the first import occurs, so the assignments done by the module aren’t repeated unnecessarily. That’s all we need in order to define a very simple Python module within our Python scripts.

Getting information from standard modules

We continue through some standard Python modules. We could get more information about methods and other entities from a specific module using the dir() method. The module has to have been previously imported as a whole (for example, using the import module instruction):

>>>import <module_name>
>>>dir(module_name)

The dir() method returns an alphabetically sorted list containing all entities’ names available in the module identified by a name passed to the function as an argument. For example, you can run the following code to print the names of all entities within the math module. You can find the following code in the get_entities_module.py file:

import math
for name in dir(math):
        print(name, end=”\t”)

In the previous script, we are using the dir() method to get all name entities from the math module.

Difference between a Python module and a Python package

Writing your own modules doesn’t differ much from writing ordinary scripts. There are some specific aspects you must be aware of, but it definitely isn’t rocket science. When we are working with Python, it is important to understand the difference between a Python module and a Python package. It is important to differentiate between them; a package is a module that includes one or more modules.

Let’s summarize some important concepts:

  • A module is a kind of container filled with functions – you can pack as many functions as you want into one module and distribute it across the world.
  • Of course, it’s generally a good idea not to mix functions with different application areas within one module, so group your functions carefully and name the module containing them in a clear and intuitive way.

Python Module Index

Python comes with a robust standard library that includes everything from built-in modules for easy I/O access to platform-specific API calls. Python’s modules make up their own universe, in which Python itself is only a galaxy, and we would venture to say that exploring the depths of these modules can take significantly more time than getting acquainted with “pure” Python. You can read about all standard Python modules here: https://docs.python.org/3/py-modindex.html.

Managing parameters in Python

Often in Python, scripts that are used on the command line as arguments are used to give users options when they run a certain command. Each argument that is provided to a Python script is exposed through the sys.argv array, which can be accessed by importing the sys module.

However, to develop this task, the best option is to use the argparse module, which comes installed by default when you install Python. For more information, you can check out the official website: https://docs.python.org/3/library/argparse.html.

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

import argparse
parser = argparse.ArgumentParser(description=’Testing parameters’)
parser.add_argument(“-p1”, dest=”param1”, help=”parameter1”)
parser.add_argument(“-p2”, dest=”param2”, help=”parameter2”) 
params = parser.parse_args()
print(“Parameter 1”,params.param1)
print(“Parameter 2”,params.param2)

One of the interesting choices is that the type of parameter can be indicated using the type attribute. For example, if we want to treat a certain parameter as if it were an integer, then we might do so as follows:

parser.add_argument(“-param”, dest=”param”, type=”int”)

Another thing that could help us to have a more readable code is to declare a class that acts as a global object for the parameters. For example, if we want to pass several parameters at the same time to a function, we could use this global object, which is the one that contains the global execution parameters.

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

import argparse
class Parameters:
“””Global parameters”””
def __init__(self, **kwargs):
     self.param1 = kwargs.get(“param1”)
     self.param2 = kwargs.get(“param2”)
def view_parameters(input_parameters):
print(input_parameters.param1)
print(input_parameters.param2)
parser = argparse.ArgumentParser(description=’Passing parameters in an object’)
parser.add_argument(“-p1”, dest=”param1”, help=”parameter1”)
parser.add_argument(“-p2”, dest=”param2”, help=”parameter2”)
params = parser.parse_args()
input_parameters = Parameters(param1=params.param1,param2=params.param2)
view_parameters(input_parameters)

In the previous script, we can see that with the argparse module, we obtain parameters and we encapsulate these parameters in an object with the Parameters class.

Python provides another class called OptionParser for managing command-line arguments. OptionParser is part of the optparse module that is provided by the standard library. OptionParser allows you to do a range of very useful things with command-line arguments:

  • Specify a default if a certain argument is not provided.
  • It supports both argument flags (either present or not) and arguments with values.
  • It supports different formats of passing arguments.

Let’s use OptionParser to manage parameters in the same way we have seen before with the argparse module. In the code provided here, command-line arguments are used to pass in these variables:

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

from optparse import OptionParser
class Parameters:
        “””Global parameters”””
        def __init__(self, **kwargs):
                self.param1 = kwargs.get(“param1”)
                self.param2 = kwargs.get(“param2”)
def view_parameters(input_parameters):
        print(input_parameters.param1)
        print(input_parameters.param2)
parser = OptionParser()
parser.add_option(“--p1”, dest=”param1”, help=”parameter1”)
parser.add_option(“--p2”, dest=”param2”, help=”parameter2”)
(options, args) = parser.parse_args()
input_parameters = Parameters(param1=options.param1,param2=options.param2)
view_parameters(input_parameters)

The previous script demonstrates the use of the OptionParser class. It provides a simple interface for command-line arguments, allowing you to define certain properties for each command-line option. It also allows you to specify default values. If certain arguments are not provided, it allows you to throw specific errors.

Now that you know how Python manages modules and packages, let’s move on to learning how to manage dependencies and create a virtual environment with the virtualenv utility.