$SAFE = 5 and Safe Ruby Misleading?

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
···

----- Original Message -----
From: Dave Fayram kirindave@lensmen.net
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.