<br><br><div><span class="gmail_quote">On 7/4/06, <b class="gmail_sendername">Ka-Ping Yee</b> &lt;<a href="mailto:python-dev@zesty.ca">python-dev@zesty.ca</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi Brett,<br><br>Here are some comments on the description of the restricted execution<br>model that you posted.<br><br>&gt; When referring to the state of an interpreter, it is either &quot;trusted&quot; or<br>&gt; &quot;untrusted&quot;.&nbsp;&nbsp;A trusted interpreter has no restrictions imposed upon any
<br>&gt; resource.&nbsp;&nbsp;An untrusted interpreter has at least one, possibly more, resource<br>&gt; with a restriction placed upon it.<br><br>In response to Guido's comment about confusing the words &quot;trusted&quot; and<br>
&quot;untrusted&quot;, how about &quot;empowered&quot; and &quot;restricted&quot;?</blockquote><div><br>Maybe.&nbsp; I am really starting to lean towards trusted and sandboxed. <br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; When the Interpreter Is Embedded<br>&gt; ================================<br>&gt;<br>&gt; Single Untrusted Interpreter<br>&gt; ----------------------------<br>&gt;<br>&gt; This use case is when an application embeds the interpreter and never has more
<br>&gt; than one interpreter running.<br>&gt;<br>&gt; The main security issue to watch out for is not having default abilities be<br>&gt; provided to the interpreter by accident.<br><br>I'd rather rephrase this in the opposite direction.&nbsp;&nbsp;The onus shouldn't
<br>be on the application to hunt down each possible dangerous authority and<br>deactivate them all one by one.&nbsp;&nbsp;The main security issue is to let the<br>application choose which abilities it wants the restricted interpreter
<br>to have, and then ensure that the restricted interpreter gets only those<br>abilities.</blockquote><div><br>Right.&nbsp; I am thinking more of an implementation screw up that somehow provides access to an object that has escalated rights.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; Multiple Untrusted Interpreters<br>&gt; -------------------------------<br>
&gt;<br>&gt; When multiple interpreters, all untrusted at varying levels, need to be<br>&gt; running within a single application.&nbsp;&nbsp;This is the key use case that this<br>&gt; proposed design is targetted for.<br>&gt;<br>&gt; On top of the security issues from a single untrusted interpreter,
<br>&gt; there is one additional worry.&nbsp;&nbsp;Resources cannot end up being leaked<br>&gt; into other interpreters where they are given escalated rights.<br><br>What is your model here for communication between interpreters?&nbsp;&nbsp;If two
<br>interpreters can communicate, any attempt to &quot;prevent leakage&quot; of<br>resources is meaningless.&nbsp;&nbsp;When you say &quot;leaked into other interpreters&quot;<br>are you talking about a Python object leaking or something else at a
<br>lower level?</blockquote><div><br>I am talking about Python objects.<br><br>As for communication, I was planning on something included directly in globals or some custom object to handle that.&nbsp; I have not been focusing on that aspect so far.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Suppose for example that the application wants to embed two interpreters,<br>P and Q, and that the application wants P to be able to write files but
<br>Q to be restricted against writing files.&nbsp;&nbsp;When you say &quot;leaked&quot; above,<br>that suggests to me that you want to prevent something like<br><br>&nbsp;&nbsp;&nbsp;&nbsp;# code running in P<br>&nbsp;&nbsp;&nbsp;&nbsp;import spam<br>&nbsp;&nbsp;&nbsp;&nbsp;f = open('/home/doofus/.ssh/authorized_keys', 'a')
<br>&nbsp;&nbsp;&nbsp;&nbsp;spam.f = f<br><br>&nbsp;&nbsp;&nbsp;&nbsp;# code running in Q<br>&nbsp;&nbsp;&nbsp;&nbsp;import spam<br>&nbsp;&nbsp;&nbsp;&nbsp;spam.f.write('blargh')<br><br>The above example supposes that P and Q can communicate through a<br>shared module, spam, where they can pass Python objects.
</blockquote><div><br>Right.&nbsp; But Python modules are separate per interpreter and only C extension modules are in any way shared between interpreters.&nbsp; But sharing an open file like that is bad and why C extension modules must be whitelisted to be used.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">But notice that even if you prevent them from passing Python objects<br>like open files, any form of communication is sufficient to leak
<br>resources:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;# code running in P<br>&nbsp;&nbsp;&nbsp;&nbsp;def add_key(key):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f = open('/home/doofus/.ssh/authorized_keys', 'a')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.write(key + '\n')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.close()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;import socket<br>&nbsp;&nbsp;&nbsp;&nbsp;s = 
socket.socket()<br>&nbsp;&nbsp;&nbsp;&nbsp;s.bind(('', 6666))<br>&nbsp;&nbsp;&nbsp;&nbsp;s.listen(1)<br>&nbsp;&nbsp;&nbsp;&nbsp;ns, addr = s.accept()<br>&nbsp;&nbsp;&nbsp;&nbsp;add_key(ns.recv(100))<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;# code running in Q<br>&nbsp;&nbsp;&nbsp;&nbsp;import webbrowser<br>&nbsp;&nbsp;&nbsp;&nbsp;webbrowser.open('<a href="http://localhost:6666/zebra'">
http://localhost:6666/zebra'</a>)<br><br>As long as P can listen for instructions from Q, it can give Q<br>the power to write to the filesystem.</blockquote><div><br>Right, which is why sockets and files are restricted and turned off by default.&nbsp; You have to give explicit permission to use either resource. 
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; Filesystem<br>&gt; ===================<br>&gt;<br>&gt; The most obvious facet of a filesystem to protect is reading from it.
<br>&gt; One does not want what is stored in ``/etc/passwd`` to get out.&nbsp;&nbsp;And<br>&gt; one also does not want writing to the disk unless explicitly allowed<br>&gt; for basically the same reason; if someone can write ``/etc/passwd``
<br>&gt; then they can set the password for the root account.<br><br>There's a big difference between modifying (or erasing) an existing file<br>and writing a new file (e.g. for temporary storage).&nbsp;&nbsp;If i give you a<br>little filesystem of your own to play in, and it starts out empty, you
<br>can put whatever you want in it without violating my secrecy or the<br>integrity of my files.<br><br>I think you should be talking about this in terms of specifically<br>what abilities you want to be able to allow, based on examples of
<br>real-life applications.</blockquote><div><br>Fair enough.&nbsp; But since you have the ability to only list files specifically, you can give temporary file access by giving access to such a non-existent file for writing.&nbsp; If you don't like an existing file then you don't get access to it.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; Physical Resources<br>&gt; ===================<br>&gt;<br>&gt; Memory should be protected.&nbsp;&nbsp;It is a limited resource on the system
<br>&gt; that can have an impact on other running programs if it is exhausted.<br>&gt; Being able to restrict the use of memory would help alleviate issues<br>&gt; from denial-of-service (DoS) attacks.<br><br>&gt; Networking
<br>&gt; ===================<br>&gt;<br>&gt; Networking is somewhat like the filesystem in terms of wanting similar<br>&gt; protections.&nbsp;&nbsp;You do not want to let untrusted code make tons of socket<br>&gt; connections or accept them to do possibly nefarious things (
e.g., acting<br>&gt; as a zombie).<br>&gt;<br>&gt; You also want to prevent finding out information about the network you are<br>&gt; connected to.&nbsp;&nbsp;This includes doing DNS resolution since that allows one<br>&gt; to find out what addresses your intranet has or what subnets you use.
<br><br>Again, it's risky to describe only individual cases of things to<br>prevent.&nbsp;&nbsp;What networking abilities are safe or necessary for the<br>kinds of applications you have in mind?&nbsp;&nbsp;Start from nothing and<br>work up from there.
</blockquote><div><br>That's the plan.&nbsp; I am planning to go through socket function by function and explicitly allow access as warranted and block everything else.&nbsp; It is not going to be &quot;let's block DNS and allow everything else&quot;.&nbsp; Sorry if that wasn't clear.&nbsp; This is mostly just to say &quot;I plan on restricting this kind of stuff, here is an example&quot;.
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; Interpreter<br>&gt; ===================<br>&gt;<br>&gt; One must make sure that the interpreter is not harmed in any way.
<br>&gt; There are several ways to possibly do this.&nbsp;&nbsp;One is generating<br>&gt; hostile bytecode.&nbsp;&nbsp;Another is some buffer overflow.&nbsp;&nbsp;In general any<br>&gt; ability to crash the interpreter is unacceptable.<br><br>This is hard for me to understand.&nbsp;&nbsp;What exactly do you trust and
<br>not trust?&nbsp;&nbsp;It seems to me that crashing an interpreter is only a<br>problem if a single interpreter is running both trusted and untrusted<br>code -- then if the untrusted code crashes the interpreter, the<br>trusted code suffers.
<br><br>But there doesn't seem to be any such thing in your model.&nbsp;&nbsp;Each<br>interpreter is either trusted or untrusted.&nbsp;&nbsp;If the interpreter is<br>trusted, and the code running in it causes it to crash, i assume<br>you would consider that to be the code's &quot;own fault&quot;, right?
<br>And if the interpreter is untrusted, and the code running in it<br>causes it to crash, then the code has only harmed itself.<br><br>It seems to me that we need only be concerned about crashing when<br>the crash of an embedded interpreter will bring down its host
<br>application, or there are multiple interpreters embedded at once<br>and one interpreter causes another interpreter to crash.</blockquote><div><br>Right.&nbsp; But being embedded, won't any segfault of an interpreter bring down the embedded application?
<br><br>But you are correct, I am only concerned with preventing a crash of a sandboxed interperter.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; Resource Hiding<br>&gt; =============================<br>[...]<br>&gt; This can be viewed as a passive system for security.<br>[...]<br>&gt; Resource Crippling<br>&gt; =============================<br>&gt; Another approach to security is to provide constant, proactive security
<br>&gt; checking of rights to use a resource.<br><br>I think you have this backwards.&nbsp;&nbsp;Resource hiding is proactive:<br>before untrusted code has a chance to abuse anything, you decide<br>what you want to allow it to do.&nbsp;&nbsp;It defaults to no access, and
<br>only gets access to resources you have proactively decided to provide.</blockquote><div><br>I am using &quot;proactive&quot; as in constantly checking the security model.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Resource crippling is the opposite: it begins by giving carte blanche<br>to the untrusted code, then you run around trying to plug holes<br>by stopping everything you don't want.&nbsp;&nbsp;This is a lot more work,<br>and it is also much more dangerous.&nbsp;&nbsp;If you forget to plug even
<br>one hole, you're hosed.</blockquote><div><br>Yeah, I know, which is why I am only bothering with 'file' and 'socket'.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Back to what you wrote about resource hiding:<br><br>&gt; This can be viewed as a passive system for security.&nbsp;&nbsp;Once a resource<br>&gt; has been given to code there are no more checks to make sure the<br>&gt; security model is being violated.
<br><br>This last sentence doesn't make any sense.&nbsp;&nbsp;If you decided to give<br>the resource, how is using the resource a violation?&nbsp;&nbsp;Either you<br>want to enable the resource or you don't.&nbsp;&nbsp;If you want to enable<br>it, give it; if you don't, don't give it.&nbsp;&nbsp;As a criticism of the
<br>resource hiding approach, it's a red herring -- there's no way<br>to interpret this sentence that doesn't make it also an<br>unfalsifiable criticism of any possible security model.</blockquote><div><br>Yeah, I figured that out after I wrote this. 
<br><br>&gt; The most common implementation of resource hiding is capabilities.<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; In this type of system a resource's reference acts as a ticket that
<br>&gt; represents the right to use the resource.&nbsp;&nbsp;Once code has a reference<br>&gt; it is considered to have full use of that resource it represents and<br>&gt; no further security checks are performed.<br><br>Same thing.&nbsp;&nbsp;What &quot;further security checks&quot; are we worried about?
<br>Woult it check to see whether we've authorized the interpreter to<br>have access to the resource ... which we already know to be true?<br><br>&gt; To allow customizable restrictions one can pass references to wrappers of
<br>&gt; resources.&nbsp;&nbsp;This allows one to provide custom security to resources instead of<br>&gt; requiring an all-or-nothing approach.<br><br>The ability to customize security restrictions is an important<br>advantage of the resource hiding approach, since resource crippling
<br>requires that the architect of the security model anticipate every<br>possible security restriction that future programmers might need.<br><br>Using resource crippling is analogous to removing &quot;def&quot; from the
<br>language and requiring Python programmers to only use functions<br>that are provided in the built-in modules instead of writing their<br>own functions.<br><br>&gt; To use an analogy, imagine you are providing security for your home.
<br>&gt; With capabilities, security came from not having any way to know<br>&gt; where your house is without being told where it was; a reference<br>&gt; to its location.&nbsp;&nbsp;You might be able to ask a guard (e.g., Java's<br>
&gt; ClassLoader) for a map, but if they refuse there is no way for you<br>&gt; to guess its location without being told.&nbsp;&nbsp;But once you knew where<br>&gt; it was, you had complete use of the house.<br><br>This analogy is only fair if you compare it to the same analogy for
<br>the resource crippling approach.&nbsp;&nbsp;Resource crippling doesn't get you<br>any finer-grained control either!&nbsp;&nbsp;The comparison story is:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;With resource crippling, security comes from having a guard<br>&nbsp;&nbsp;&nbsp;&nbsp;at the door to your house.&nbsp;&nbsp;When a Python interpreter comes
<br>&nbsp;&nbsp;&nbsp;&nbsp;up to the door, the guard checks to see if the interpreter<br>&nbsp;&nbsp;&nbsp;&nbsp;has permission to enter the house, and if it does, then it<br>&nbsp;&nbsp;&nbsp;&nbsp;gets complete use of the house.<br><br>Why is the granularity of control described as the whole house
<br>in the resource-hiding story, but as each door in the house in<br>the resource-crippling story?</blockquote><div><br>Because, as you said above, if you want someone to have the resource (the house, or in more concrete terms, a 'file') you just give it to them.&nbsp; If you cripple it, though, you might provide a 'file' object but restrict how many bytes are written.
<br><br>But I also realize that resource hiding handles this by providing a wrapper that provides the protection.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt; And that complete access is an issue with a capability system.<br>&gt; If someone played a little loose with a reference for a resource<br>&gt; then you run the risk of it getting out.<br><br>Could you be more specific about what you mean by &quot;it getting out&quot;?
</blockquote><div><br>Out of a trusted interpreter and ending up in a sandboxed interpreter some how.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
If you mean getting from a trusted interpreter to an untrusted<br>interpreter -- then how is a resource going to travel between<br>interpreters?</blockquote><div><br>Beats me, but I am always scared of Armin and Samuele.&nbsp; =)
<br></div><br>It seems that your criticisms are aimed at resource crippling being a &quot;plug holes as needed but if you foul up you are screwed&quot; with resource hiding being more &quot;fix the fundamental issues and just don't present access to resources you don't want to give access to (or wrap accordingly)&quot;.&nbsp; And in general I agree with this assessment.&nbsp; But I also realize that Python was not designed for security in mind and there seems to be new ways to get access to 'file'.&nbsp; If I felt confident that I could find and hide 'file' as needed, I would go that route immediately.&nbsp; But I don't think I can (and Armin has said this as well).
<br><br>If you think you can help figure out every place a reference to 'file' can be found through the standard interpreter, then fine, let's go that way.&nbsp; I just don't have faith this can be done effectively.<br><br>-Brett
<br><br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Or if not, then are you thinking of a situation in which one<br>piece of code is trusted with the resource, but another piece of
<br>code is not, and both are running in the same interpreter?<br></blockquote><div>&nbsp;</div><br></div>