-
Notifications
You must be signed in to change notification settings - Fork 167
Add draft for ISP Fall 2024 Assignment 2.1 #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,300 @@ | ||
| # 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 implement a defense monitor to oversee file | ||
| operations in Repy. The monitor will enhance the default Repy behavior by adding | ||
| support for a default file to be used when files are opened without creating them first. | ||
| This defense monitor will ensure that software follows certain rules and guidelines, preventing potential unauthorized actions. | ||
|
|
||
| You should write test applications to ensure your reference monitor behaves | ||
| properly in different cases and to test attacks against your monitor. | ||
|
|
||
|
|
||
| ### Specifications: | ||
|
|
||
| 1. Your defense monitor should incorporate all the standard file operation methods, from opening a file, reading and writing to it, to closing and deleting it. | ||
|
|
||
| 2. In addition, if a specially named file - `default` - exists, it shall be used as a template when opening files without creating them first. | ||
| Eg: Calling `openfile('foo', True)` should create and open a new empty file called `foo` (assuming it's not present already). However, calling `openfile('foo', False)` should create a new file using `default` as the template. If `default` doesn't exist, throw the relevant error (`FileNotFoundError`). | ||
|
|
||
| 3. If default is created, written to, or deleted, then all closed files that were previously created gets deleted. Any files that are already open must be left unchanged. | ||
|
|
||
| Three design paradigms are at work in this assignment: accuracy, efficiency, and | ||
| security. | ||
|
|
||
| * Accuracy: The defense monitor should precisely and consistently manage file | ||
| operations. Only specific operations, such as `openfile()`, should have their | ||
| behavior modified. 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. For example, you may not call `readat()` | ||
| everytime `writeat()` is called. It is permissable to call `readat()` upon | ||
| `fileopen()`, however. | ||
|
|
||
| * Security: The defense layer should be robust against tampering and | ||
| circumvention. Attackers must not be able to bypass, disable, or exploit the | ||
| defense monitor's enhanced behaviors, ensuring the integrity and intended | ||
| functionality of file operations. | ||
|
|
||
|
|
||
| ### 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 applications: | ||
|
|
||
| ```bash | ||
| python2 repy.py restrictions.default encasementlib.r2py [security_layer].r2py [application].r2py | ||
| ``` | ||
|
|
||
| (Replace `[security_layer].r2py` and `[application].r2py` by the names of the | ||
| security layers and application 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. | ||
|
|
||
| You should not get any errors (or outputs) when running the test. If not, 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 sample security layer, it is not complete and does | ||
| not handle all cases required by the API. 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. | ||
| You can use the code given below as a template for your reference monitor. | ||
|
|
||
| You may save the file as `reference_monitor_[netid].r2py`. | ||
|
|
||
| ```py | ||
| """ | ||
| This security layer inadequately handles the default functionality | ||
|
|
||
| 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 | ||
|
|
||
| """ | ||
| TYPE = "type" | ||
| ARGS = "args" | ||
| RETURN = "return" | ||
| EXCP = "exceptions" | ||
| TARGET = "target" | ||
| FUNC = "func" | ||
| OBJC = "objc" | ||
|
|
||
|
|
||
| class LPFile(): | ||
| def __init__(self, filename, create): | ||
| # globals | ||
| mycontext['debug'] = False | ||
|
Comment on lines
+144
to
+145
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should have a small amount of code here to explain how their code may work. Maybe just copy default if it exists?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about this instead ? Or would it be too much ? Also this code would make the attack case work too. def __init__(self, filename, create):
# globals
mycontext['debug'] = False
if create == False and 'default' in listfiles():
default_file = openfile('default', False)
content = default_file.readat(None, 0) # Read from the file using the sandbox's readat
self.LPfile = openfile(filename, True)
self.LPfile.writeat(content, 0)
default_file.close()
else:
self.LPfile = openfile(filename, create)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, this makes sense
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've modified the doc to add this. Also, removed any references to the attack case throwing |
||
|
|
||
| if create == False and 'default' in listfiles(): | ||
| default_file = openfile('default', False) | ||
| content = default_file.readat(None, 0) # Read from the file using the sandbox's readat | ||
| self.LPfile = openfile(filename, True) | ||
| self.LPfile.writeat(content, 0) | ||
| default_file.close() | ||
| else: | ||
| self.LPfile = openfile(filename, create) | ||
|
|
||
| def readat(self, num_bytes, offset): | ||
| return self.LPfile.readat(num_bytes, offset) | ||
|
|
||
| def writeat(self, data, offset): | ||
| self.LPfile.writeat(data, offset) | ||
|
|
||
| def close(self): | ||
| self.LPfile.close() | ||
|
|
||
| def LPopenfile(filename, create): | ||
| return LPFile(filename, create) | ||
|
|
||
| def LPremovefile(filename): | ||
| removefile(filename) | ||
|
|
||
|
|
||
| # The code below sets up type checking and variable hiding for you. | ||
| # You should not change anything below this point. | ||
| sec_file_def = { | ||
| "obj-type": LPFile, | ||
| "name": "LPFile", | ||
| "writeat": {"type": "func", "args": (str, (int, long)), "exceptions": Exception, "return": (int, type(None)), "target": LPFile.writeat}, | ||
| "readat": {"type": "func", "args": ((int, long, type(None)), (int, long)), "exceptions": Exception, "return": str, "target": LPFile.readat}, | ||
| "close": {"type": "func", "args": None, "exceptions": Exception, "return": (bool, type(None)), "target": LPFile.close} | ||
| } | ||
|
|
||
| CHILD_CONTEXT_DEF["openfile"] = { | ||
| TYPE: OBJC, | ||
| ARGS: (str, bool), | ||
| EXCP: Exception, | ||
| RETURN: sec_file_def, | ||
| TARGET: LPopenfile | ||
| } | ||
|
|
||
| CHILD_CONTEXT_DEF["removefile"] = { | ||
| TYPE: FUNC, | ||
| ARGS: (str,), | ||
| EXCP: Exception, | ||
| RETURN: type(None), | ||
| TARGET: LPremovefile | ||
| } | ||
|
|
||
| # 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 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. | ||
|
|
||
| A valid attack case is found below. | ||
|
|
||
| You may save the file as `[netid]_attackcase.r2py`. | ||
|
|
||
| ```py | ||
| # Clean up if the files exist | ||
| if "default" in listfiles(): | ||
| removefile("default") | ||
| if "testfile.txt" in listfiles(): | ||
| removefile("testfile.txt") | ||
|
|
||
| # Create a default file | ||
| default = openfile("default", True) | ||
|
|
||
| # Initial write to default | ||
| default.writeat("TEMPLATE", 0) | ||
|
|
||
| # Close default | ||
| default.close() | ||
|
|
||
| # Open a file that doesn't exist | ||
| myfile = openfile("testfile.txt", False) | ||
|
|
||
| # Read from the file. | ||
| # Passing None as first argument indicates that we want to read the whole file from offset 0. | ||
| assert myfile.readat(None, 0) == "TEMPLATE" | ||
|
|
||
| # Close the file | ||
| myfile.close() | ||
| ``` | ||
|
|
||
| The given defense layer should not output any errors when used with this simple attack case. | ||
| However, you need to modify the reference monitor and the attack case to account for any possible scenario. | ||
|
|
||
| **Note:** All attacks should be written as Repy V2 files, using the `.r2py` extension. | ||
|
|
||
|
|
||
| ### Choice of File Names | ||
|
|
||
| Filenames may only be in the current directory and may only contain lowercase | ||
| letters, numbers, the hyphen, underscore, and period characters. Also, filenames | ||
| cannot be '.', '..', the blank string or start with a period. There is no | ||
| concept of a directory or a folder in repy. Filenames must be no more than 120 | ||
| characters long. | ||
|
|
||
|
|
||
| ### Running your security layer | ||
|
|
||
| Finally, type the following command at the terminal to run your security layer | ||
| with your attack program. | ||
|
|
||
| ```bash | ||
| python repy.py restrictions.default encasementlib.r2py reference_monitor_[netid].r2py [netid]_attackcase.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: | ||
| **[https://ssl.engineering.nyu.edu/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: | ||
|
|
||
| ```bash | ||
| 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 single repy file called `reference_monitor_[netid].r2py` with all | ||
| letters in lowercase. If your net id is abcd123, then the file you upload must be named `reference_monitor_abcd123.r2py`. | ||
|
|
||
| * Your task is to implement the reference monitor to try to account for all scenarios implied by the given [Specifications](#specifications). | ||
|
|
||
| * **Never raise unexpected errors or produce any output.** Your reference monitor must | ||
| produce no output when run normally, with a valid attack case. Make sure that you remove any `log()` statements used for debugging before submission. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.