Forum: Ruby $SAFE =4 safe enough?

05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 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
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 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
05be5d6610e2c3f1780aa0e39e902e93?d=identicon&s=25 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?
F48118fe74b0c7f6fd82a0ee422fa34e?d=identicon&s=25 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.
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 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.)
F48118fe74b0c7f6fd82a0ee422fa34e?d=identicon&s=25 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?
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 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
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 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
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.