diff --git a/EducationalAssignments/ParityPartOne.md b/EducationalAssignments/ParityPartOne.md new file mode 100644 index 00000000..a00f30c4 --- /dev/null +++ b/EducationalAssignments/ParityPartOne.md @@ -0,0 +1,324 @@ +# Implement a Defensive Security System + +This assignment will help you understand security mechanisms. You will be +guided through the steps of creating a reference monitor using the security +layer functionality in Repy V2. A reference monitor is an access control +concept that refers to an abstract machine that mediates all access to +objects by subjects. This can be used to allow, deny, or change the +behavior of any set of calls. While not a perfect way of validating your +reference monitor, it is useful to create test cases to see whether your +security layer will work as expected. (The test cases may be turned in as +part of the next assignment.) + +This assignment is intended to reinforce concepts about access control and +reference monitors in a hands-on manner. + + + + + + +## Overview +---- +In this assignment you will create a security layer which prevents writes that +do not maintain even parity for all 8 byte-aligned sequences in a file. +(What this means is described more precisely below.) Parity is often used to +detect errors or tampering for data. + +Your security layer will purely focus on storage of information in a file. +Using the minimal number of read blocks possible, you must determine if an +operation would change the parity. Your security layer must track enough +information about the parity of any 8-byte sequences read so that it need not +read the sequence more often than is necessary. + +All write operations must either complete or be blocked. All writes that would +not cause the parity of a 8-byte sequence to be non-even must be permitted. +Any write that would cause the parity of any 8-byte sequence to be non-even +must be blocked by throwing a RepyParityError exception. + +Note that in some cases there will be an incomplete sequence (e.g., the last +5 bytes of a 13 byte file). Parity is not checked for an incomplete sequence +(it is only checked when the sequence is completed). + +Note that the behavior of other system calls must not be changed in a way +that is visible to the running program. Reading from a file, opening a file, +etc. must appear to operate in the same manner. + +Three design paradigms are at work in this assignment: accuracy, +efficiency, and security. + + * Accuracy: The security layer should stop writeat calls if-and-only-if +they would result in non-even parity. All other actions should be allowed. +For example, if an app tries to read data a file or write data that results +in even parity 8-byte sequences these operations must succeed as per normal +and must not be blocked. All situations that are not described above *must* +match that of the underlying API. + + * Efficiency: The security layer should use a minimum number of resources, +so performance is not compromised. In particular, the security layer may not +read more 8-byte sequences than are necessary. Hint: it is *always* possible +to read two or fewer 8 byte blocks per writeat(). + + * Security: The attacker should not be able to circumvent the security +layer. Hence, if the attacker can cause a file with a non-even 8-byte sequence +to be written then the security is compromised, for example. + + +### Parity and 8-byte sequences + +For this assignment a file is conceptually broken up into 8-byte sequences. +Every consecutive series of 8 bytes (from the beginning of a file) is its own +8-byte sequence. So, the first 8 bytes (bytes 1-8) are the first sequence, the +next 8 bytes (bytes 9-16) are the second, etc. + +Note that a write may be performed on a non-8-byte-aligned portion of the +file. E.g., bytes 5-17 may be written in a single write. For that write, the +first, second, and third 8 byte sequence are all modified. + +In terms of parity, each byte has a parity based upon its value when calling +ord() in python. Each byte that has a parity divisible by 2 is considered to +be even. An 8-byte sequence is considered to be even if there are an even +number of non-even bytes in the sequence. In other words, if there are 0, +2, 4, 6, or 8 non-even bytes, the sequence is considered to be even. Also, +if a sequence has not been completely written (because it is at the end of a +file), it is always considered to have even parity for the purposes of a +write being allowed or blocked. + + +### Getting Python and RepyV2 + +Please refer to the [SeattleTestbed Build Instructions](../Contributing/BuildInstructions.md#prerequisites) +for details. + +Once you have built RepyV2 into a directory of your choice, change into that +directory. Use the command below in order to run your RepyV2 programs: + +```python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [program].r2py``` + +(Replace `[security_layer].r2py` and `[program].r2py` by the names of the +security layers and program that you want to run.) + +In order to test whether or not these steps worked, please copy and paste +the code found below for the sample security layer and sample attack. + +If you got an error, please go through the troubleshooting section found below. + +### Troubleshooting Repy code +---- +If you can't get Repy files to run, some of the following common errors may +have occurred: + + * using `print` instead of `log`: + +Repy is a subset of Python, but its syntax is slightly different. For +example, Python's `print` statement cannot be used; Repy has `log` for +that. For a full list of acceptable syntax please see +[https://github.com/SeattleTestbed/docs/blob/master/Programming/RepyV2API.md] + + * command line errors: + +**files are missing:** In the above command line call, you must have +`repy.py`, restrictions.default, encasementlib.r2py, the security layer and +the program you want to run in the current working directory. If any or +all of the above files are not in that directory then you will not be able +to run repy files. + + + + +### Tutorials for Repy and Python +---- +Now that you have Repy and Python, you may need a refresher on how to use +them. The following tutorials provide this information. + + * Official [Python tutorial](http://docs.python.org/tutorial/) + * [Differences between RepyV2 and Python](../Programming/PythonVsRepyV2.md) + * List of [RepyV2 API calls](../Programming/RepyV2API.md) + + + +## Building the security layer +---- +The following program is a basic and incomplete sample code for you to get +an idea about writing security layer. Remember, you have no idea how the +attacker will try to penetrate your security layer, so it is important that +you leave nothing to chance! + + +### A basic (and inadequate) defense + +Time to start coding! Let's inspect a basic security layer. + +``` +""" +This security layer inadequately handles parity for files in RepyV2. + + + +Note: + This security layer uses encasementlib.r2py, restrictions.default, repy.py and Python + Also you need to give it an application to run. + python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [attack_program].r2py + + """ + +class EvenParityFile(): + def __init__(self,filename,create): + # globals + mycontext['debug'] = False + # local (per object) reference to the underlying file + self.fn = filename + + self.file = openfile(self.fn,create) + + + def writeat(self,data,offset): + + # check the parity of the data written + # NOTE: This is wrong in many ways!!!! + thisdata = data + while thisdata: + eightbytesequence = thisdata[:8] + thisdata = thisdata[8:] + even = True + for thisbyte in eightbytesequence: + # for each byte, if it is odd, flip even to be the opposite + if ord(thisbyte) % 2: + even = not even + + # actually call write, if we are supposed to... + if even: + self.file.writeat(eightbytesequence,offset) + # ...or error out. + else: + raise RepyParityError("Non-even parity write to file") + + + def readat(self,bytes,offset): + # Read from the file using the sandbox's readat... + return self.file.readat(bytes,offset) + + def close(self): + self.file.close() + + +def parityopenfile(filename, create): + return EvenParityFile(filename,create) + + + + +# The code here sets up type checking and variable hiding for you. You +# should not need to change anything below here. +sec_file_def = {"obj-type":EvenParityFile, + "name":"EvenParityFile", + "writeat":{"type":"func","args":(str,(int,long)),"exceptions":Exception,"return":(int,type(None)),"target":EvenParityFile.writeat}, + "readat":{"type":"func","args":((int,long,type(None)),(int,long)),"exceptions":Exception,"return":str,"target":EvenParityFile.readat}, + "close":{"type":"func","args":None,"exceptions":None,"return":(bool,type(None)),"target":EvenParityFile.close} + } + +CHILD_CONTEXT_DEF["openfile"] = {"type":"objc","args":(str,bool),"exceptions":Exception,"return":sec_file_def,"target":parityopenfile} + +# Execute the user code +secure_dispatch_module() +``` + + + +### Testing your security layer +---- +In this part of the assignment you will pretend to be an attacker. Remember +the attacker's objective is to bypass the parity restrictions or cause +the security layer to act in a disallowed manner. By understanding how the +attacker thinks, you will be able to write better security layers. + +An example of a test / attack is found below: + +``` +if "testfile.txt" in listfiles(): + removefile("testfile.txt") + +myfile=openfile("testfile.txt",True) #Create a parity file + +# put some valid data in the file. +myfile.writeat("AA",0) + +# I should be able to read it out. +assert('AA' == myfile.readat(None,0)) + +# However, this write should fail... +try: + myfile.writeat("BCBCBC",2) +except RepyParityError: + pass # should happen +else: + log("should have been an error instead!") + +#Close the file +myfile.close() + + +``` + +**Note:** All attacks should be written as Repy V2 files, using the .r2py extension. + +#### Choice of File Names +---- +It is important to keep in mind that only lowercase file names are allowed. +So in the above code, specifically: + +``` +# Open a file +myfile=openfile("look.txt",True) +``` + +look.txt is a valid file name, however Look.txt and LOOK.TXT are not. +Examples of other invalid files names are, _look.txt, look/.txt, and +look().txt. Essentially all non-alphanumeric characters are not allowed. + +### Running your security layer +---- +Finally, type the following commands at the terminal to run your security +layer with your attack program + +```python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [attack_program].r2py ``` + +Make sure you went through the "How to get RepyV2" section! + + +# Notes and Resources +---- + + * For a complete list of syntax in Repyv2 please visit: + * **[https://github.com/SeattleTestbed/docs/blob/master/Programming/RepyV2API.md]** + + * The following link is an excellent source for information about security layers: **[http://isis.poly.edu/~jcappos/papers/cappos_seattle_ccs_10.pdf]** + + * **Note:** It is possible to add multiple security layers to Repy, this +may be useful for testing different mitigations separately. This is +done with the following command at the terminal: + +```python repy.py restrictions.default encasementlib.r2py [security_layer1].r2py [security_layer2].r2py [security_layer3].r2py [program].r2py``` + +**Your security layer must produce no output!! ** + + * In repy log replaces print from python. This may be helpful when +testing if Repy installed correctly. + +# What to turn in? +---- + * Turn in a repy file called reference_monitor_[ netid ].r2py with all +letters in lowercase. + +* **Never raise unexpected errors or produce any output.** Your program +must produce no output when run normally.