From: djd15@... Date: 2003-08-13T03:37:11+09:00 Subject: Re: $SAFE = 5 and Safe Ruby Misleading? ----- Original Message ----- From: Dave Fayram Date: Tuesday, August 12, 2003 2:01 pm Subject: Re: $SAFE = 5 and Safe Ruby Misleading? > djd15@cwru.edu wrote: > > $SAFE allows you to contain malicious code and > > keep it from damaging the system, but if you allow > > code to be passed out to a trusted environment, > > then I think the burden would be on you to make > > sure somehow that the object isn't malicious (not > > that that's even possible, like you've said). > > > > It seems to me that what you're asking would take > > a very complex security system (Java's system is > > quite complex and it doesn't get it right), and > > I don't think $SAFE was designed to cover it. > > Yeah. There is no way to check. Further, there is no way to even > be sure your > data from even a simple case is secure? Pass out a string? No, > that won't > work, they overrided =~. Badness. A hash is just as bad. It's almost > impossiboe to detect a really devious person doing this, since > they could > uncode and execute highly obfuscated strings. > > Which is why I'm curious what $SAFE = 4 is meant to do? It's easy > to make it > so that code runs in a box, what's difficult is to get data out of > that box. > > The only solution I can think of is for an object's methods and > class methods > to be frozen (no aliasing, no adding, no removing) but its > variables still be > mutable. With that constraint, with some care you could write a > Ruby program > that could execute totally untrusted code and return meaninful > values from it. > Well, I'm not sure I totally agree with that. It is possible to get data out of a $SAFE=4 process, as people have shown. However, you can only get data out, not functionality. For example, you have your $SAFE=4 thread do some calculations, and need to get that to the trusted thread. Depending on the data, you could dump it to a file, or set up a socket to send the raw data in either text or some sort of binary format. You can dump hashes to YAML, for example. What you can't do is send objects out of the $SAFE=4 thread directly. Data is not the same as objects (which I think is really the key to solving your problem). Objects contain data and functionality, and the functionality is the real problem. Another way to do it (borrowing an idea that someone posted here already), is to pass the unknown object to a $SAFE=4 thread that you've programmed, and copy the relevant data into a known class. Like: safe = Thread.start { $SAFE=4 str = untrusted.call String.new str }.value As Matz did. Now you know that the result is of class String, with no methods redefined (unless the untrusted code can redefine methods of core classes, in which case you can't execute any untrusted code anyway). This is a simplistic example, but you can always copy the relevant information if it's accessible. The only thing this prevents is the untrusted code providing new functionality by writing new classes or redefining methods in a non-malicious way, but I can't think of any real way to distinguish between the two (other than, as I said before, tagging each object as allowed or not allowed to perform certain operations in their methods, which would be very complex). So you can get data out of $SAFE threads safely. The only remaining case is if the data itself is malicious, but Ruby can't really handle that for you (i.e. make sure you're not calling "eval safe" above without first checking what string safe is). I don't think the situation is as hopeless as you surmise. Cheers. - Dan