Forum: Ruby $SAFE =4 safe enough?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Farrel Lifson (Guest)
on 2006-08-29 23:26
(Received via mailing list)
I'm implementing a system where users will be able to execute short
snippets of ruby code and It'll be executing in a thread with $SAFE
set to 4. From my reading it seems like there have been some
vulnerabilities where users can run some mischevous code. Is this
still the case? I know _why is working on Sandbox but I don't think I
will have it avaiable in my environment. I'm basically doing something
like the following:

thread = Thread.new do
  $SAFE=4
  instance_eval(userCode)
end
# 10 second timeout
if !thread.join(10)
  thread.kill
end

That tries to get rid of any potential DOS style attacks. Is there
anything else that could go wrong with this approach?

Farrel
Eric Hodel (Guest)
on 2006-08-29 23:46
(Received via mailing list)
On Aug 29, 2006, at 2:26 PM, Farrel Lifson wrote:
>  instance_eval(userCode)
> end
> # 10 second timeout
> if !thread.join(10)
>  thread.kill
> end
>
> That tries to get rid of any potential DOS style attacks. Is there
> anything else that could go wrong with this approach?

999999**99999
Thread.critical = true

There are other things that will DOS a $SAFE = 4 sandbox.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
Farrel Lifson (Guest)
on 2006-08-30 08:48
(Received via mailing list)
On 29/08/06, Eric Hodel <drbrain@segment7.net> wrote:
> >  $SAFE=4
> 999999**99999
>
>
>

Would  undef'ing Thread#criticial= before calling instance_eval help
in this regard?
snacktime (Guest)
on 2006-08-30 09:24
(Received via mailing list)
There really isn't anything you can do to make this safe.  Even $SAFE
itself can be set to a different value from the usercode.  Plus ruby
threads aren't real threads, so I think someone could just fork off a
new process, or at the least it would be easy to lock up your whole
application by calling some blocking operation that takes forever.
Ken Bloom (Guest)
on 2006-08-30 21:36
(Received via mailing list)
snacktime <snacktime@gmail.com> wrote:
> There really isn't anything you can do to make this safe.  Even $SAFE
> itself can be set to a different value from the usercode.

No, it can't. At lower levels it throws a SecurityError saying it
can't downgrade the safe level. At higher levels, it throws a
SecurityError saying it can't "can't chage global variable value"
(i.e. the rules of Level 4 inherently prevent you from changing the
security level.)
snacktime (Guest)
on 2006-08-30 22:26
(Received via mailing list)
On 8/30/06, Ken Bloom <kbloom@gmail.com> wrote:
> snacktime <snacktime@gmail.com> wrote:
> > There really isn't anything you can do to make this safe.  Even $SAFE
> > itself can be set to a different value from the usercode.
>
> No, it can't. At lower levels it throws a SecurityError saying it
> can't downgrade the safe level. At higher levels, it throws a
> SecurityError saying it can't "can't chage global variable value"
> (i.e. the rules of Level 4 inherently prevent you from changing the
> security level.)

Ya you are correct, it won't let you change the safe level.  I wonder
how hard it would be to bypass it though using something like
rubyinline?
Eric Hodel (Guest)
on 2006-08-31 02:16
(Received via mailing list)
On Aug 30, 2006, at 12:23 AM, snacktime wrote:

> There really isn't anything you can do to make this safe.  Even $SAFE
> itself can be set to a different value from the usercode.

$SAFE can only be increased.

$ ruby -e '$SAFE = 1; $SAFE = 0'-e:1: tried to downgrade safe level
from 1 to 0 (SecurityError)

> Plus ruby threads aren't real threads, so I think someone could
> just fork off a
> new process,

Not at $SAFE >= 2

$ ruby -e '$SAFE = 2; fork do puts "hi" end'
-e:1:in `fork': Insecure operation `fork' at level 2 (SecurityError)
         from -e:1

> or at the least it would be easy to lock up your whole application
> by calling some blocking operation that takes forever.

Yes.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
Eric Hodel (Guest)
on 2006-08-31 02:22
(Received via mailing list)
On Aug 30, 2006, at 1:24 PM, snacktime wrote:

>> security level.)
>
> Ya you are correct, it won't let you change the safe level.  I wonder
> how hard it would be to bypass it though using something like
> rubyinline?

Easy for $SAFE <= 3:

$ cat desafe.rb
require 'rubygems'
require 'inline'

class DeSafe
   inline do |builder|
     builder.prefix "RUBY_EXTERN int ruby_safe_level;"

     builder.c <<-EOC
       static void
       reduce() {
         ruby_safe_level = 0;
       }
     EOC
   end
end


$SAFE = ARGV.shift.to_i rescue 0

p $SAFE

DeSafe.new.reduce

p $SAFE

$ rm -fr ~/.ruby_inline/; ruby desafe.rb 4
desafe.rb:20:in `write': Insecure operation `write' at level 4
(SecurityError)
         from desafe.rb:20:in `p'
         from desafe.rb:20
$ rm -fr ~/.ruby_inline/; ruby desafe.rb 3
3
0

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
This topic is locked and can not be replied to.