|
| 1 | +# Fixing your security layer |
| 2 | + |
| 3 | +In this assignment you will analyze the bugs in your security layer from [Part |
| 4 | +One](./ImmutableVersionOne.md) |
| 5 | +and fix them. You may want to use test cases from [Part |
| 6 | +Two](./ImmutableVersionTwo.md) |
| 7 | +to help identify these bugs. |
| 8 | + |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +In this assignment you are fixing your reference monitor. You have been given a |
| 13 | +bunch of test programs that try to compromise your reference monitor. Your job |
| 14 | +will be to determine where your reference monitor failed, and fix it to ensure |
| 15 | +an attacker cannot circumvent the security layer. |
| 16 | + |
| 17 | +## Code Analysis |
| 18 | + |
| 19 | +Given below is a section taken from the sample reference monitor given |
| 20 | +in [Part One](./ImmutableVersionOne.md#a-basic-and-inadequate-defense). |
| 21 | + |
| 22 | +```py |
| 23 | +class VMFile(): |
| 24 | + def __init__(self, filename, create): |
| 25 | + # globals |
| 26 | + # If a file with the same 'filename' already exists, this creates a new version 'filename.v1'. |
| 27 | + # (Incomplete: does not handle further versions like v2, v3, etc.) |
| 28 | + if create: |
| 29 | + if filename in listfiles(): |
| 30 | + # File exists → create version 1 |
| 31 | + # bug ? |
| 32 | + prev_file = openfile(filename, False) |
| 33 | + content = prev_file.readat(None, 0) |
| 34 | + |
| 35 | + new_name = filename + ".v1" |
| 36 | + self.VMfile = openfile(new_name, True) |
| 37 | + self.VMfile.writeat(content, 0) |
| 38 | + else: |
| 39 | + # File doesn't exist → create filename |
| 40 | + # bug ? |
| 41 | + self.VMfile = openfile(filename, True) |
| 42 | + else: |
| 43 | + # Open existing file normally |
| 44 | + self.VMfile = openfile(filename, False) |
| 45 | + |
| 46 | + def readat(self, num_bytes, offset): |
| 47 | + # bug ? |
| 48 | + return self.VMfile.readat(num_bytes, offset) |
| 49 | + |
| 50 | + def writeat(self, data, offset): |
| 51 | + # bug ? |
| 52 | + return self.VMfile.writeat(data, offset) |
| 53 | + |
| 54 | + def close(self): |
| 55 | + return self.VMfile.close() |
| 56 | + |
| 57 | + |
| 58 | +def LPopenfile(filename, create): |
| 59 | + # bug ? |
| 60 | + return VMFile(filename, create) |
| 61 | + |
| 62 | +def LPremovefile(filename): |
| 63 | + removefile(filename) |
| 64 | + |
| 65 | +def LPlistfiles(): |
| 66 | + # bug ? |
| 67 | + return listfiles() |
| 68 | +``` |
| 69 | + |
| 70 | +Let's analyze some of the bugs in this implementation (not in any specific order). |
| 71 | + |
| 72 | +1. As outlined in the specifications in [PartOne](./ImmutableVersionOne.md), if the openfile() is called on an already open file, then the relevant error (`FileInUseError`) must be thrown. This scenario is not correctly handled in the sample implementation. |
| 73 | + |
| 74 | +2. Similarly, if the create=True is used on a versioned file, it should raise RepyArgumentError("Cannot create explicit version files"), as manual version creation is not allowed. |
| 75 | + |
| 76 | +3. The reference monitor needs to track the state of the information on disk, but cannot re-read it for every access (due to efficiency concerns). A common mistake is when the attacker can cause the reference monitor’s state to diverge from the underlying system’s state, especially in error conditions. The reference monitor and disk's states should be in sync. |
| 77 | + |
| 78 | +4. Race conditions and Time-of-check-to-time-of-use (TOCTTOU) issues are frequent oversights. Attackers may exploit timing gaps between checks and operations to corrupts state or bypass restrictions. Such bugs can cause inconsistencies or even infinite loops in the reference monitor. |
| 79 | + |
| 80 | +5. Some reference monitors inappropriately share state for different files. An attacker may be able to exploit this and cause security and accuracy issues. |
| 81 | + |
| 82 | +6. Many reference monitors had accuracy or security bugs as a result of not properly following the instructions. |
| 83 | + |
| 84 | +7. Finally, this example doesn't use locks, which makes it vulnerable to multi-threaded race conditions - effectively the same root cause as TOCTTOU problems but arising from concurrent access. |
| 85 | + |
| 86 | + |
| 87 | +## What to turn in? |
| 88 | + |
| 89 | +* Submit 2 files: |
| 90 | + 1. 1 r2py file: Your reference monitor should be named as `reference_monitor_[netid].r2py` with all |
| 91 | +letters in lowercase . For example, if your netid is `abc123`, the file should be named: `reference_monitor_abc123.r2py`. |
| 92 | + 2. 1 pdf file: Write up a 1 page report explaining the rationale behind the vulnerabilities and how you fixed them. Name it `[netid].pdf`. |
| 93 | + |
| 94 | +* **Never raise unexpected errors or produce any output.** Your reference monitor must |
| 95 | +produce no output when run normally, with a valid attack case. Make sure that you remove any `log()` statements used for debugging before submission. |
| 96 | + |
| 97 | +* You are required to modify your reference monitor so that it generates no output (logs or errors) when any valid attack case (from Part 2.2, after invalid attack cases have been identified and excluded) is executed against it. |
0 commit comments