|
| 1 | +# Implement a Defensive Security System |
| 2 | + |
| 3 | +This assignment will help you understand security mechanisms. You will be |
| 4 | +guided through the steps of creating a reference monitor using the security |
| 5 | +layer functionality in Repy V2. A reference monitor is an access control |
| 6 | +concept that refers to an abstract machine that mediates all access to |
| 7 | +objects by subjects. This can be used to allow, deny, or change the |
| 8 | +behavior of any set of calls. While not a perfect way of validating your |
| 9 | +reference monitor, it is useful to create test cases to see whether your |
| 10 | +security layer will work as expected. (The test cases may be turned in as |
| 11 | +part of the next assignment.) |
| 12 | + |
| 13 | +This assignment is intended to reinforce concepts about access control and |
| 14 | +reference monitors in a hands-on manner. |
| 15 | + |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +## Overview |
| 22 | +---- |
| 23 | +In this assignment you will create a security layer which prevents writes that |
| 24 | +do not maintain even parity for all 8 byte-aligned sequences in a file. |
| 25 | +(What this means is described more precisely below.) Parity is often used to |
| 26 | +detect errors or tampering for data. |
| 27 | + |
| 28 | +Your security layer will purely focus on storage of information in a file. |
| 29 | +Using the minimal number of read blocks possible, you must determine if an |
| 30 | +operation would change the parity. Your security layer must track enough |
| 31 | +information about the parity of any 8-byte sequences read so that it need not |
| 32 | +read the sequence more often than is necessary. |
| 33 | + |
| 34 | +All write operations must either complete or be blocked. All writes that would |
| 35 | +not cause the parity of a 8-byte sequence to be non-even must be permitted. |
| 36 | +Any write that would cause the parity of any 8-byte sequence to be non-even |
| 37 | +must be blocked by throwing a RepyParityError exception. |
| 38 | + |
| 39 | +Note that in some cases there will be an incomplete sequence (e.g., the last |
| 40 | +5 bytes of a 13 byte file). Parity is not checked for an incomplete sequence |
| 41 | +(it is only checked when the sequence is completed). |
| 42 | + |
| 43 | +Note that the behavior of other system calls must not be changed in a way |
| 44 | +that is visible to the running program. Reading from a file, opening a file, |
| 45 | +etc. must appear to operate in the same manner. |
| 46 | + |
| 47 | +Three design paradigms are at work in this assignment: accuracy, |
| 48 | +efficiency, and security. |
| 49 | + |
| 50 | + * Accuracy: The security layer should stop writeat calls if-and-only-if |
| 51 | +they would result in non-even parity. All other actions should be allowed. |
| 52 | +For example, if an app tries to read data a file or write data that results |
| 53 | +in even parity 8-byte sequences these operations must succeed as per normal |
| 54 | +and must not be blocked. All situations that are not described above *must* |
| 55 | +match that of the underlying API. |
| 56 | + |
| 57 | + * Efficiency: The security layer should use a minimum number of resources, |
| 58 | +so performance is not compromised. In particular, the security layer may not |
| 59 | +read more 8-byte sequences than are necessary. Hint: it is *always* possible |
| 60 | +to read two or fewer 8 byte blocks per writeat(). |
| 61 | + |
| 62 | + * Security: The attacker should not be able to circumvent the security |
| 63 | +layer. Hence, if the attacker can cause a file with a non-even 8-byte sequence |
| 64 | +to be written then the security is compromised, for example. |
| 65 | + |
| 66 | + |
| 67 | +### Parity and 8-byte sequences |
| 68 | + |
| 69 | +For this assignment a file is conceptually broken up into 8-byte sequences. |
| 70 | +Every consecutive series of 8 bytes (from the beginning of a file) is its own |
| 71 | +8-byte sequence. So, the first 8 bytes (bytes 1-8) are the first sequence, the |
| 72 | +next 8 bytes (bytes 9-16) are the second, etc. |
| 73 | + |
| 74 | +Note that a write may be performed on a non-8-byte-aligned portion of the |
| 75 | +file. E.g., bytes 5-17 may be written in a single write. For that write, the |
| 76 | +first, second, and third 8 byte sequence are all modified. |
| 77 | + |
| 78 | +In terms of parity, each byte has a parity based upon its value when calling |
| 79 | +ord() in python. Each byte that has a parity divisible by 2 is considered to |
| 80 | +be even. An 8-byte sequence is considered to be even if there are an even |
| 81 | +number of non-even bytes in the sequence. In other words, if there are 0, |
| 82 | +2, 4, 6, or 8 non-even bytes, the sequence is considered to be even. Also, |
| 83 | +if a sequence has not been completely written (because it is at the end of a |
| 84 | +file), it is always considered to have even parity for the purposes of a |
| 85 | +write being allowed or blocked. |
| 86 | + |
| 87 | + |
| 88 | +### Getting Python and RepyV2 |
| 89 | + |
| 90 | +Please refer to the [SeattleTestbed Build Instructions](../Contributing/BuildInstructions.md#prerequisites) |
| 91 | +for details. |
| 92 | + |
| 93 | +Once you have built RepyV2 into a directory of your choice, change into that |
| 94 | +directory. Use the command below in order to run your RepyV2 programs: |
| 95 | + |
| 96 | +```python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [program].r2py``` |
| 97 | + |
| 98 | +(Replace `[security_layer].r2py` and `[program].r2py` by the names of the |
| 99 | +security layers and program that you want to run.) |
| 100 | + |
| 101 | +In order to test whether or not these steps worked, please copy and paste |
| 102 | +the code found below for the sample security layer and sample attack. |
| 103 | + |
| 104 | +If you got an error, please go through the troubleshooting section found below. |
| 105 | + |
| 106 | +### Troubleshooting Repy code |
| 107 | +---- |
| 108 | +If you can't get Repy files to run, some of the following common errors may |
| 109 | +have occurred: |
| 110 | + |
| 111 | + * using `print` instead of `log`: |
| 112 | + |
| 113 | +Repy is a subset of Python, but its syntax is slightly different. For |
| 114 | +example, Python's `print` statement cannot be used; Repy has `log` for |
| 115 | +that. For a full list of acceptable syntax please see |
| 116 | +[https://github.com/SeattleTestbed/docs/blob/master/Programming/RepyV2API.md] |
| 117 | + |
| 118 | + * command line errors: |
| 119 | + |
| 120 | +**files are missing:** In the above command line call, you must have |
| 121 | +`repy.py`, restrictions.default, encasementlib.r2py, the security layer and |
| 122 | +the program you want to run in the current working directory. If any or |
| 123 | +all of the above files are not in that directory then you will not be able |
| 124 | +to run repy files. |
| 125 | + |
| 126 | +<!-- |
| 127 | +AR: This doesn't apply when building from source or getting the runtime tarball only (it does for clearinghouse downloads). |
| 128 | + * Downloading the wrong version of seattle: |
| 129 | +
|
| 130 | +Seattle is operating system dependent. If you download the Windows |
| 131 | +version, you need to use the Windows command line. For Windows 7 this is |
| 132 | +PowerShell. You can open a new terminal by going to start, search, type |
| 133 | +powershell. If you downloaded the Linux version you must use a Linux OS |
| 134 | +and Linux terminal. |
| 135 | +
|
| 136 | +--> |
| 137 | + |
| 138 | + |
| 139 | +### Tutorials for Repy and Python |
| 140 | +---- |
| 141 | +Now that you have Repy and Python, you may need a refresher on how to use |
| 142 | +them. The following tutorials provide this information. |
| 143 | + |
| 144 | + * Official [Python tutorial](http://docs.python.org/tutorial/) |
| 145 | + * [Differences between RepyV2 and Python](../Programming/PythonVsRepyV2.md) |
| 146 | + * List of [RepyV2 API calls](../Programming/RepyV2API.md) |
| 147 | + |
| 148 | + |
| 149 | + |
| 150 | +## Building the security layer |
| 151 | +---- |
| 152 | +The following program is a basic and incomplete sample code for you to get |
| 153 | +an idea about writing security layer. Remember, you have no idea how the |
| 154 | +attacker will try to penetrate your security layer, so it is important that |
| 155 | +you leave nothing to chance! |
| 156 | + |
| 157 | + |
| 158 | +### A basic (and inadequate) defense |
| 159 | + |
| 160 | +Time to start coding! Let's inspect a basic security layer. |
| 161 | + |
| 162 | +``` |
| 163 | +""" |
| 164 | +This security layer inadequately handles parity for files in RepyV2. |
| 165 | +
|
| 166 | +
|
| 167 | +
|
| 168 | +Note: |
| 169 | + This security layer uses encasementlib.r2py, restrictions.default, repy.py and Python |
| 170 | + Also you need to give it an application to run. |
| 171 | + python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [attack_program].r2py |
| 172 | + |
| 173 | + """ |
| 174 | +
|
| 175 | +class EvenParityFile(): |
| 176 | + def __init__(self,filename,create): |
| 177 | + # globals |
| 178 | + mycontext['debug'] = False |
| 179 | + # local (per object) reference to the underlying file |
| 180 | + self.fn = filename |
| 181 | + |
| 182 | + self.file = openfile(self.fn,create) |
| 183 | +
|
| 184 | +
|
| 185 | + def writeat(self,data,offset): |
| 186 | + |
| 187 | + # check the parity of the data written |
| 188 | + # NOTE: This is wrong in many ways!!!! |
| 189 | + thisdata = data |
| 190 | + while thisdata: |
| 191 | + eightbytesequence = thisdata[:8] |
| 192 | + thisdata = thisdata[8:] |
| 193 | + even = True |
| 194 | + for thisbyte in eightbytesequence: |
| 195 | + # for each byte, if it is odd, flip even to be the opposite |
| 196 | + if ord(thisbyte) % 2: |
| 197 | + even = not even |
| 198 | + |
| 199 | + # actually call write, if we are supposed to... |
| 200 | + if even: |
| 201 | + self.file.writeat(eightbytesequence,offset) |
| 202 | + # ...or error out. |
| 203 | + else: |
| 204 | + raise RepyParityError("Non-even parity write to file") |
| 205 | + |
| 206 | + |
| 207 | + def readat(self,bytes,offset): |
| 208 | + # Read from the file using the sandbox's readat... |
| 209 | + return self.file.readat(bytes,offset) |
| 210 | +
|
| 211 | + def close(self): |
| 212 | + self.file.close() |
| 213 | +
|
| 214 | +
|
| 215 | +def parityopenfile(filename, create): |
| 216 | + return EvenParityFile(filename,create) |
| 217 | +
|
| 218 | +
|
| 219 | +
|
| 220 | +
|
| 221 | +# The code here sets up type checking and variable hiding for you. You |
| 222 | +# should not need to change anything below here. |
| 223 | +sec_file_def = {"obj-type":EvenParityFile, |
| 224 | + "name":"EvenParityFile", |
| 225 | + "writeat":{"type":"func","args":(str,(int,long)),"exceptions":Exception,"return":(int,type(None)),"target":EvenParityFile.writeat}, |
| 226 | + "readat":{"type":"func","args":((int,long,type(None)),(int,long)),"exceptions":Exception,"return":str,"target":EvenParityFile.readat}, |
| 227 | + "close":{"type":"func","args":None,"exceptions":None,"return":(bool,type(None)),"target":EvenParityFile.close} |
| 228 | + } |
| 229 | +
|
| 230 | +CHILD_CONTEXT_DEF["openfile"] = {"type":"objc","args":(str,bool),"exceptions":Exception,"return":sec_file_def,"target":parityopenfile} |
| 231 | +
|
| 232 | +# Execute the user code |
| 233 | +secure_dispatch_module() |
| 234 | +``` |
| 235 | + |
| 236 | + |
| 237 | + |
| 238 | +### Testing your security layer |
| 239 | +---- |
| 240 | +In this part of the assignment you will pretend to be an attacker. Remember |
| 241 | +the attacker's objective is to bypass the parity restrictions or cause |
| 242 | +the security layer to act in a disallowed manner. By understanding how the |
| 243 | +attacker thinks, you will be able to write better security layers. |
| 244 | + |
| 245 | +An example of a test / attack is found below: |
| 246 | + |
| 247 | +``` |
| 248 | +if "testfile.txt" in listfiles(): |
| 249 | + removefile("testfile.txt") |
| 250 | +
|
| 251 | +myfile=openfile("testfile.txt",True) #Create a parity file |
| 252 | +
|
| 253 | +# put some valid data in the file. |
| 254 | +myfile.writeat("AA",0) |
| 255 | +
|
| 256 | +# I should be able to read it out. |
| 257 | +assert('AA' == myfile.readat(None,0)) |
| 258 | +
|
| 259 | +# However, this write should fail... |
| 260 | +try: |
| 261 | + myfile.writeat("BCBCBC",2) |
| 262 | +except RepyParityError: |
| 263 | + pass # should happen |
| 264 | +else: |
| 265 | + log("should have been an error instead!") |
| 266 | + |
| 267 | +#Close the file |
| 268 | +myfile.close() |
| 269 | +
|
| 270 | +
|
| 271 | +``` |
| 272 | + |
| 273 | +**Note:** All attacks should be written as Repy V2 files, using the .r2py extension. |
| 274 | + |
| 275 | +#### Choice of File Names |
| 276 | +---- |
| 277 | +It is important to keep in mind that only lowercase file names are allowed. |
| 278 | +So in the above code, specifically: |
| 279 | + |
| 280 | +``` |
| 281 | +# Open a file |
| 282 | +myfile=openfile("look.txt",True) |
| 283 | +``` |
| 284 | + |
| 285 | +look.txt is a valid file name, however Look.txt and LOOK.TXT are not. |
| 286 | +Examples of other invalid files names are, _look.txt, look/.txt, and |
| 287 | +look().txt. Essentially all non-alphanumeric characters are not allowed. |
| 288 | + |
| 289 | +### Running your security layer |
| 290 | +---- |
| 291 | +Finally, type the following commands at the terminal to run your security |
| 292 | +layer with your attack program |
| 293 | + |
| 294 | +```python repy.py restrictions.default encasementlib.r2py [security_layer].r2py [attack_program].r2py ``` |
| 295 | + |
| 296 | +Make sure you went through the "How to get RepyV2" section! |
| 297 | + |
| 298 | + |
| 299 | +# Notes and Resources |
| 300 | +---- |
| 301 | + |
| 302 | + * For a complete list of syntax in Repyv2 please visit: |
| 303 | + * **[https://github.com/SeattleTestbed/docs/blob/master/Programming/RepyV2API.md]** |
| 304 | + |
| 305 | + * The following link is an excellent source for information about security layers: **[http://isis.poly.edu/~jcappos/papers/cappos_seattle_ccs_10.pdf]** |
| 306 | + |
| 307 | + * **Note:** It is possible to add multiple security layers to Repy, this |
| 308 | +may be useful for testing different mitigations separately. This is |
| 309 | +done with the following command at the terminal: |
| 310 | + |
| 311 | +```python repy.py restrictions.default encasementlib.r2py [security_layer1].r2py [security_layer2].r2py [security_layer3].r2py [program].r2py``` |
| 312 | + |
| 313 | +**Your security layer must produce no output!! ** |
| 314 | + |
| 315 | + * In repy log replaces print from python. This may be helpful when |
| 316 | +testing if Repy installed correctly. |
| 317 | + |
| 318 | +# What to turn in? |
| 319 | +---- |
| 320 | + * Turn in a repy file called reference_monitor_[ netid ].r2py with all |
| 321 | +letters in lowercase. |
| 322 | + |
| 323 | +* **Never raise unexpected errors or produce any output.** Your program |
| 324 | +must produce no output when run normally. |
0 commit comments