Skip to content

Commit aa9d1fb

Browse files
authored
Merge pull request #38 from SeattleTestbed/JustinCappos-ParityAssignment
Create ParityPartOne.md
2 parents 75c5103 + e3bdc2e commit aa9d1fb

File tree

1 file changed

+324
-0
lines changed

1 file changed

+324
-0
lines changed
Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
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

Comments
 (0)