From: Ano Hito Date: 2013-02-11T15:14:25+09:00 Subject: Re: Why doesn't Ruby have a built in sandbox class? Robert Klemme wrote in post #1096190: > You make it sound as if people who use $SAFE would not know exactly > how it works. Not so much that they wouldn't know how it works, but that it may provide a false sense of security. Just look at this (http://blog.segment7.net/2006/08/30/reducing-safe) and this (http://www.h-online.com/open/news/item/Multiple-vulnerabilities-in-Ruby-safe-level-and-dl-tainting-736893.html). Safe levels work by blacklisting things you don't want to be available to untrusted code. The problem with this is the same problem with any type of blacklisting, it violates the principle of least privilege (http://en.wikipedia.org/wiki/Principle_of_least_privilege). While it may be nice to think you can be secure by not letting code have access to things that could be dangerous, it is practically impossible to predict what is or isn't dangerous in every given scenario. It's always a better idea to use an approach that allows untrusted code access to what it needs to function, and only what it needs to function. Safe levels don't do that. > I am not a regular user of $SAFE and at the moment I have no idea what > use cases you are referring to here. Can you share some more detail, > please? Why himself actually listed several cases in the original README for his sandbox: * Start small interpreters which can periodically be dumped and restarted. (Long-running apps can self-upgrade!) * Load multiple different versions of a library. Maybe you're converting an old version to a new version. * Run multiple Rails apps. (Rails is a classic example of a crowded namespace where two apps' set of modules cannot coexist.) I would additionally add to that the ability to run your code under a hypervisor for added security, even in cases where you trust the code you're running. And of course, that I believe sandboxes are in general, more secure than blacklisting. > Did you mean #method_missing instead of #send? I could be wrong about this, but I think send is the only method a ruby object is actually required to have. Otherwise you couldn't call on the object to do anything. You could use method_missing, but you'd still need to have a send method, because I'm pretty sure method_missing only gets called in the event that the send method fails. > I think there are some issues with wrappers. Assuming object X lives > in object space A and was thrown into objectspace B. Y and Z are > other objects private to object space B. > > 1. A method call from Y to X which passes Z as argument would > implicitly export Z to A. For a sandbox it would not make sense to > _implicitly_ export something to another box (object space). Wouldn't it? I think that you have to keep in mind that most of what you're doing in a sandbox is interacting with the stuff already in the box. In cases where you allow outside stuff to go in, you should generally keep it restricted to objects that act as controlled interfaces between what's outside the box and what's inside the box. That being said in order to prevent massive unintentional leaks of objects into a box from occurring, it would probably be a good idea to make it so you could only access the methods of an object exported to a box if it's class had also already been exported. > 2. How far in the object graph starting at Z do you want to go with > wrapper creation? It's not that you only export Z to A but also a > whole lot other objects. This is not only a security issue (item 1) > but also a performance issue because you would need a recursive wrap > of all objects. If you're referring to doing something like wrapping all the objects referenced to by the instance variable of objects being wrapped, you wouldn't do that. All method calls to the object would switch the object space of the current thread to the object's native space, in which all of it's references would already be valid. Granted the context switching would be a drag on performance, but you wouldn't be doing it that much, because your general goal is to limit the interaction of things in the box with things outside of it. > 3. How do you ensure objects stay inside their boxes if you > automatically create wrappers for method arguments? It seems the > situation is not that different as with a single global object space. While you don't necessarily keep objects in only a single space by doing this, at the least you maintain control over what they can access. Any reference to a foreign object, be it in the original object space or the one you're using for a sandbox, is always going to be wrapped. It's methods will always execute inside of it's native object space. Even when an object leaves the box, it never truly leaves the box. > The situation would be easier if you allowed for object graphs > starting at method arguments only objects which are known to the > target object space, i.e. disallow implicit migration. I am not so > sure though whether that solution is so far away from $SAFE - or > creating separate processes which communicate via DRb. I'm not quite sure how what you're saying would work. Could you elaborate a bit? > I believe your suggestion certainly needs more thinking. Before we > talk about implementations we should clarify requirements - even more > so as this is a security topic. It couldn't hurt. I mean, if someone does seriously consider implementing sandboxing as a native feature of ruby, the last thing I'd want is for it to turn into a security disaster that gets scrapped before it ever hits a stable release. I will however say that sandboxing is a tried an true approach to securely executing code. My version of sandboxing is slightly different from the typical because I was trying to think of something that would be more in line with the way ruby already works, and not something that would require dozens of hacks to implement. If any ruby devs want to jump in here and tell me all the reasons a more traditional sandbox would be a million times easier to implement, I'm all ears. > I am pretty sure it's too late to include such a fundamental > architectural change into Ruby 2.0. That sounds more like a Ruby 3.0 > thing. Is ruby 2.0 getting close to release then? I honestly haven't been following ruby's development closely enough to keep up on these things, but I was assuming 2.0 was still at least a year away. Well, while implementing native sandboxing may require some architectural reshuffling, it wouldn't require any changes to the ruby environment itself that wouldn't be more or less backward compatible with all existing code. The only thing I could think of is if you'd written code that specifically depended on ObjectSpace not having a new method, but I'm not sure that would come up very often. Maybe someone could still sneak sandboxes into 2.0, you never know. >PS: I forgot one thing: thank you for starting that interesting >discussion! My pleasure. ;) I've been a long time user of ruby for my personal scripting needs, but I've never really done much as far as contributing to the greater ruby scene. Well, there's this (https://github.com/An0Hit0/Ruby-ISO-9660), which is useful, despite being unfinished. Anyway, I'd like to contribute a bit more, but after looking at the ruby source code, it became apparent it would take more time than I have to familiarize myself with the code enough that I could even approach the issue of implementing sandboxes, let alone actually doing it. -- Posted via http://www.ruby-forum.com/.