$SAFE = 5 and Safe Ruby Misleading?

K

kirindave

Hey folks.

With all this talk of duck typing and such, I got to thinking about some of my
code that I *thought* executed untrusted code relatively safely. I'd run code
in a safe 5 thread, let it return a string, which I checked to make sure it
was a "string." However, I now realize that concept is totally meaningless.

Unless I'm misunderstanding, doesn't this mean that there is no such thing as
an object you can "trust" in an absolute sense in Ruby. So, with that in mind,
someone could return an object that, to me as the receiver, looks like a
string, but its actual purpose is to iterate over every object in the runtime,
looking for database like objects, with the purpose of destroying them. Or it
could try and erase as much as it could.

I know these objects come out tainted, but in order to use them, we need to
untaint them. How do I know that that .upper! isn't actually going to destroy
me?

The only way I can see it is if an object could be "partially frozen", its
methods and class methods locked, but its member variables not locked. I don't
think there's any way to achieve this.

Am I totally wrong about this?

--
Dave Fayram
(e-mail address removed)
(e-mail address removed)
Coder / Idealist
--
 
B

Brian Candler

With all this talk of duck typing and such, I got to thinking about some of my
code that I *thought* executed untrusted code relatively safely. I'd run code
in a safe 5 thread, let it return a string, which I checked to make sure it
was a "string." However, I now realize that concept is totally meaningless.

Unless I'm misunderstanding, doesn't this mean that there is no such thing as
an object you can "trust" in an absolute sense in Ruby. So, with that in mind,
someone could return an object that, to me as the receiver, looks like a
string, but its actual purpose is to iterate over every object in the runtime,
looking for database like objects, with the purpose of destroying them. Or it
could try and erase as much as it could.

I know these objects come out tainted, but in order to use them, we need to
untaint them. How do I know that that .upper! isn't actually going to destroy
me?

You're right in one sense - if someone has rights to modify core objects and
classes in your Ruby environment, then you're toast whatever way you look at
it.

However the assumption is that these tainted objects come from an external,
non-Ruby environment, and typically this means they come in as objects of a
fixed type, such as String. (Examples: data taken from ENV, data taken from
stdin, data taken from CGI GET or POST parameters)

So someone cannot send you a general Ruby object, unless you were to
explicitly unmarshal it, and they cannot directly touch your Ruby run-time
environment. If they could, they could redefine ENV to return whatever they
like, or they could simply override methods in your classes to do whatever
they liked.

But given that you have (say) a string from an untrusted source, you can
untaint it like:

foo = ENV['HTTP_HOST']
if /\A[a-zA-Z0-9.-]+\z/ =~ foo
foo.untaint
else
raise "Oi! No!"
end

The idea being that maybe you want to do something like
system("nslookup -q=a #{foo}")
but clearly certain values of foo are dangerous, like "; rm -rf /*"
The tainting mechanism just forces you to think about what values of a
variable may or may not be safe before you use them in system calls,
filenames, and such like.

BEWARE: Don't use /^...$/ in this case, use /\A...\z/

irb(main):001:0> evil = "foo\nrm -rf /*"
=> "foo\nrm -rf /*"
irb(main):002:0> evil =~ /^foo$/
=> 0
irb(main):003:0> evil =~ /\Afoo\z/
=> nil

Regards,

Brian.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,430
Messages
2,571,676
Members
48,796
Latest member
Greg L.

Latest Threads

Top