Ssd Unit 7

5 minute read

Published:

Unit 7

Learning Outcomes Achieved

  1. Critically analyse development problems and determine appropriate methodologies, tools and techniques to solve them
  2. Design, develop and adapt programs and to produce a solution that meets the design brief and critically evaluate solutions that are produced

A Simple Python Shell

import subprocess

HELP_TEXT = """Available Commands:
HELP- displays this screen.
LIST- displays all files in a directory.
ADD <n1> <n2>- Adds the two given numbers and prints the result.
EXIT- Closes the shell."""

def init_shell():
    while True:
        user_input = input()

        # Split command at spaces to obtain the operator on its own.
        # If no argument is given to split(), it will split at any whitespace
        inputs = user_input.split()
        operator = inputs[0]

        # Do not trust user inputs, create an abstraction between the shell and user commands
        # by relying on string matching and send commands to the shell by using hardcoded strings
        # written by the developer
        if operator == "LIST":
            # use the dir command since it's cross-platform (Microsoft, 2017; Free Software Foundation, 2020)
            result = subprocess.run(["dir"], stdout=subprocess.PIPE)
            print(result.stdout.decode("utf-8"))
        elif operator == "HELP":
            print(HELP_TEXT)
        elif operator == "ADD":
            # Use list unpacking and list slicing for convenience
            n1, n2 = inputs[1:]
            # EAFP approach is a best practice in Python
            try:
                # Convert to float to ensure that decimals can be added,
                # not just integers
                print(float(n1) + float(n2))
            except ValueError:
                print(f"Invalid operand(s) received, inputs must be numeric: n1={n1}, n2={n2}")
        elif operator == "EXIT":
            break
        else:
            print(f"Unknown command received: {user_input}")
            print(HELP_TEXT)

init_shell()

Vulnerabilities

The main vulnerability in this program is that it is an ordinary file and is therefore susceptible to tampering. Any form of file manipulation could be used if the path is known.

In terms of alternative solutions, if this application was written using Python 2, the input() command would be susceptible to command injection attacks because the input() command doesn’t automatically convert received values into strings (StackHawk, 2021). As an example, consider the following code:

# Execute within a Python 2 environment as a script of its own

user_input = input("Enter something: ")
  
print "You entered: ", user_input

An attacker could run the script and type the following literal to start accessing sensitive information (i.e. __import__('os').getcwd()):

Enter something: __import__('os').getcwd()

Causing the following to be printed:

You entered: /home/codio/workspace

This proves that access could be granted to the operating system directly from the script, enabling various operations to be completed. Note that the __import__() method allows imports to be written on one line and returns the imported library (Python Software Foundation, 2020), allowing an attacker to use virtually any library (and its corresponding methods) available to the operating system. This is easily avoided by updating the code to use Python 3, because the Python 3 version of input() converts all given text to a string.

Completing this exercise enabled me to achieve learning outcomes 2 and 3, because I was required to find a way to develop a program according to a specification, and then critically analyze the security of the solution by finding vulnerabilities within my proposed solution (and its alternatives). This exercise taught me how to examine a piece of software from different points of view to find ways in, and I will improve the security of the code I write by aapplying this type of thinking.

Seminar

This week, a seminar discussion was also held. During the seminar, I presented my implementation of the shell, and received feedback from my tutor. The tutor asked me if the usage of if/else could be inefficient, and I did not realise this is true until it was brought up. I then responded by saying that the code could be made more efficicent if a dictionary was used instead. I was also asked how the functionality of the add function could be extended, and if I remember correctyly, I replied by saying that the add method would have to be updated if more arguments were desired to be taken. I did think about mentioning variadic arguments, but was unsure if Python supports them. They would allow for infinite amounts of numbers to be added.

In addition, we discussed some other points that I would like to revisit. One interesting point was that multithreaded code is good for making the most of available system resources, however, it is hard to debug. We also revised the Saltzer and Schroeder principles, and were asked about our opinions on it and how we will apply it.

Through the seminar, I achieved learning outcome 2 because we discussed how software interacts with operating systems, the implications of that interaction, and how an OS can be designed safely.

References

Python Software Foundation. (2020) Built-in Functions. Available from: https://docs.python.org/2/library/functions.html#import [Accessed 1 November 2021]. StackHawk. (2021) Command Injection in Python: Examples and Prevention. Available from: https://www.stackhawk.com/blog/command-injection-python/ [Accessed 1 November 2021].