Save the world from evil code crusade

Hello!
It's my (Aureliano) again.

I'm trying to implement something similar to the Java Security Manager
for Ruby. The project is currently in prealpha stage at rubyforge
(http://securedruby.rubyforge.org).

But Ruby is different from Java because it's much more dinamic. And I
like it because of it!. But it brings some issues regarding code
redefinition. What I'm trying to achieve is a way to run untrusted code
in the ruby interpreter and don't worry about possible damages to the
system. "Will this code erase all my home directory?" (or "format my
harddrive?", if I'm root) is a valid concern. Of course, in Ruby you
can always check the source code just looking at it. But, what if you
have a >100000 lines script that does something interesting but you
don't trust because your archinemesis wrote it? What if you wan't to
use "eval" to run user input code?

I think I'm able to stop direct file accesses but, because of the
dinamicity (does such word exist?) of ruby, malign code (malign as the
Austin Power archinemesis, Dr. Evil) might redefine methods to trick
our good and helpless code to do something evil for the human kind (ok,
I'm exaggerating a little bit here). For instance imagine this:

evil.rb:
class Object
  def chomp a
     # it's really evil.
     "a name of a file that if's erased the world will be destroyed"
  end
end

good_and_dumb.rb:
require "evil" # did I told you the dumb part?
FileUtils.delete(chomp "erase_to_save_the_world.doc")

Well, the world is doomed. But If we were able to stop evil to redefine
chomp, this wouldn't happen. That's why I need a way to selectively
stop method definition/redefinition/removal.

But I'm unable to find a way to implement it in a pure ruby way. Do you
know any? All the good and dumb ruby code in the world will thank you.

Please post back,
thank you very much,
Aureliano.

aurelianito wrote:

Hello!
It's my (Aureliano) again.

I'm trying to implement something similar to the Java Security Manager
for Ruby. The project is currently in prealpha stage at rubyforge
(http://securedruby.rubyforge.org).

If detecting malicious code is essentially impossible, would it be a reasonable alternative to compile a version of Ruby that simply could not do Bad Things? Change or remove all methods of potential evil. No 'system', no file manipulation, no 'dl', that sort of thing. Then execute all foreign code in this sandboxed version.

James

···

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

aurelianito wrote:

I'm trying to implement something similar to the Java Security Manager
for Ruby. The project is currently in prealpha stage at rubyforge
(http://securedruby.rubyforge.org).

Why are you trying to implement this? If it's just for fun & greater understanding of Ruby, then, well, good luck. :slight_smile: And my guess in that case is that you're going to have to develop a pre-processor or interpreter through which everything is fed, or you're going to have to modify Ruby's C code*. I'd also guess that any general implementation you come up with will not be seen as useful -- not because it's no good, but because there's no perceived need in the Ruby community for such a thing right now.

If it's for a purpose (for use in some other project of yours), then I'd suggest to focus on the particular aspect of security that affects you. If it's file access, then relying on operating-system ACLs might be your best bet, as ES suggested. Of course having the ACLs for a process change _while it's running_ is outside the scope of the setuid bit, so, again, context is needed. Are these plugins? 'Servlets'? What is the code you're trying to hamper and how is it being served?

In any case, I'd suggest to narrow your scope to one particular item of security at a time, if only to subdivide your task into tacklable subtasks.

Devin

*Or this:
Module.constants.each { |const|
  self.class.send :remove_const, const
}
self.class.ancestors.each { |mod|
  mod.class_eval {
    instance_methods.each {|meth| undef_method meth}
  }
}
puts 'hello'

But I imagine there's a leak somewhere in there.

I think saving the world from evil code is a laudable aim, but if
you're ever going to save us from things like this:

  ruby -e'$><<([*$<]|[])' infile > outfile

then you'll have to whack Mark Hubbart (see ruby-talk/159649) which I
doubt is possible even in E.

Sean

P.S. :wink:

"aurelianito" <aurelianocalvo@yahoo.com.ar> writes:

Hello!
It's my (Aureliano) again.

I'm trying to implement something similar to the Java Security Manager
for Ruby. The project is currently in prealpha stage at rubyforge
(http://securedruby.rubyforge.org).

Have a look at this, maybe it helps:

                JAR Security Kernel

You possibly need to restrict Ruby in some way to allow for an
unmodifyable lambda calculus.

···

thank you very much,
Aureliano.

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Hi!

I've sumarized some of your questions and added them to the secured
ruby wiki. The link is
http://securedruby.rubyforge.org/wiki/wiki.pl?FrequentlyAskedQuestions.
Please let me know and/or modify this page if you believe something is
wrong or missing.

Thank you very much for your patience and feedback,
Aureliano.

PS: If you feel like contributing to this project, you are more than
welcome.

Thread.new do
  $SAFE = 4
  # Do what you want
end

Sandboxed and all.

···

On Saturday 08 October 2005 09:09, James Britt wrote:

aurelianito wrote:
> Hello!
> It's my (Aureliano) again.
>
> I'm trying to implement something similar to the Java Security Manager
> for Ruby. The project is currently in prealpha stage at rubyforge
> (http://securedruby.rubyforge.org).

If detecting malicious code is essentially impossible, would it be a
reasonable alternative to compile a version of Ruby that simply could
not do Bad Things? Change or remove all methods of potential evil. No
'system', no file manipulation, no 'dl', that sort of thing. Then
execute all foreign code in this sandboxed version.

The idea is to have something like the Java SecurityManager.
I would like to have PARTS (files, for instance) of the code that I
don't trust.
Removing the methods is useless, because I want to be able to run them.

It's the first item of a lot of personal projects (dreams) I have.
I'll name a few:

* Hosting services can set permissions for each ruby on rails (or
another ruby framework) application. All the applications run in the
same Apache instance.
* Ruby Web Start (combine the securedruby extension with rubygems and
voila!, ruby applications run from any web-server and they don't break
the user's computer).
* Implement a pure ruby version of the Seti program. Users would
download several projects simultaneously and they don't have to bother
to secure their machines from the code that is downloaded to them.

All these projects need fine grained security constraints like the Java
Virtual Machine has. But Ruby is a better language than Java and I
prefer to be able to run the code in a free platform (free as defined
by the Free Software Foundation). And I prefer to use an existing
language than start from scratch.

And, by the way, this is a personal project. I wanted to have the
feeling to program in a highly dynamic language. Most of my
professional experience is in Java and I feel I'm missing something.
That's why I'm tackling a problem that goes to the root of the
language.

I'm glad you asked.
Aureliano.

···

>I'm trying to implement something similar to the Java Security Manager
>for Ruby. The project is currently in prealpha stage at rubyforge
>(http://securedruby.rubyforge.org).
>
>
Why are you trying to implement this? If it's just for fun & greater
understanding of Ruby, then, well, good luck. :slight_smile: And my guess in that
case is that you're going to have to develop a pre-processor or
interpreter through which everything is fed, or you're going to have to
modify Ruby's C code*. I'd also guess that any general implementation
you come up with will not be seen as useful -- not because it's no good,
but because there's no perceived need in the Ruby community for such a
thing right now.

If it's for a purpose (for use in some other project of yours), then I'd
suggest to focus on the particular aspect of security that affects you.
If it's file access, then relying on operating-system ACLs might be your
best bet, as ES suggested. Of course having the ACLs for a process
change _while it's running_ is outside the scope of the setuid bit, so,
again, context is needed. Are these plugins? 'Servlets'? What is the
code you're trying to hamper and how is it being served?

In any case, I'd suggest to narrow your scope to one particular item of
security at a time, if only to subdivide your task into tacklable subtasks.

Devin

*Or this:
Module.constants.each { |const|
  self.class.send :remove_const, const
}
self.class.ancestors.each { |mod|
  mod.class_eval {
    instance_methods.each {|meth| undef_method meth}
  }
}
puts 'hello'

But I imagine there's a leak somewhere in there.

Kevin Brown wrote:

···

On Saturday 08 October 2005 09:09, James Britt wrote:

aurelianito wrote:

Hello!
It's my (Aureliano) again.

I'm trying to implement something similar to the Java Security Manager
for Ruby. The project is currently in prealpha stage at rubyforge
(http://securedruby.rubyforge.org).

If detecting malicious code is essentially impossible, would it be a
reasonable alternative to compile a version of Ruby that simply could
not do Bad Things? Change or remove all methods of potential evil. No
'system', no file manipulation, no 'dl', that sort of thing. Then
execute all foreign code in this sandboxed version.

Thread.new do
  $SAFE = 4
  # Do what you want
end

Sandboxed and all.

Guaranteed?

James

I want to be able to define different capabilities for different parts
of the code. I also wan't to be able to run "eval" without worring
about potencial problems (not disabling eval, like it would be the case
if $SAFE == 4). It's a different security model from the "tainting"
model that is used in Perl and Ruby.

I really don't mean any offense by this, but you picked a pretty un-Ruby-ish problem to start with, I think. That might make it hard to learn Ruby and its merits.

I really don't mean to discourage you though. Best of luck with your projects.

James Edward Gray II

···

On Oct 8, 2005, at 3:26 PM, aurelianito wrote:

And, by the way, this is a personal project. I wanted to have the
feeling to program in a highly dynamic language. Most of my
professional experience is in Java and I feel I'm missing something.
That's why I'm tackling a problem that goes to the root of the
language.

of the code. I also wan't to be able to run "eval" without worring
about potencial problems (not disabling eval, like it would be the case
if $SAFE == 4). It's a different security model from the "tainting"
model that is used in Perl and Ruby.

moulon% ruby -e '$SAFE = 4; eval "1+1"'
moulon%

Guy Decoux

James Edward Gray II wrote:

And, by the way, this is a personal project. I wanted to have the
feeling to program in a highly dynamic language. Most of my
professional experience is in Java and I feel I'm missing something.
That's why I'm tackling a problem that goes to the root of the
language.

I really don't mean any offense by this, but you picked a pretty un- Ruby-ish problem to start with, I think. That might make it hard to learn Ruby and its merits.

Or, viewed another way, trying to get something to do the sorts of things it isn't typically inclined to do can be enlightening.

For example, if you wanted to turn Java into a fluid, dynamic language, you'd certainly have to learn about all the restrictive, cramped parts.

Modifying or wrapping Ruby to make is less fluid and dynamic seems quite an educational task; for starters, you'll probably end up knowing the internals far better than most users.

James

···

On Oct 8, 2005, at 3:26 PM, aurelianito wrote:

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Hi,

···

In message "Re: Save the world from evil code crusade" on Sun, 9 Oct 2005 00:22:13 +0900, James Britt <james_b@neurogami.com> writes:

Sandboxed and all.

Guaranteed?

No. But we are trying to make it as safe and useful as possible, as
other parts of Ruby.

              matz.

But I would need to run a new process and I don't want to do that.
I also don't want to run a new thread.
I also wan't to be able to write SOME files (not all of them).
The $SAFE level model is broken when you want more granularity. I wan't
to be able to pick and choose what I let or not let some code do.

Yukihiro Matsumoto wrote:

Hi,

>> Sandboxed and all.
>
>Guaranteed?

No. But we are trying to make it as safe and useful as possible, as
other parts of Ruby.

Can't ask for more than that!

Thanks,

James

···

In message "Re: Save the world from evil code crusade" > on Sun, 9 Oct 2005 00:22:13 +0900, James Britt <james_b@neurogami.com> writes:

--

http://www.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys

Hi --

···

On Sun, 9 Oct 2005, aurelianito wrote:

But I would need to run a new process and I don't want to do that.
I also don't want to run a new thread.
I also wan't to be able to write SOME files (not all of them).
The $SAFE level model is broken when you want more granularity. I wan't
to be able to pick and choose what I let or not let some code do.

I think the only way to do that fully is to write the code yourself
:slight_smile:

Threads give you some granularity. Why don't you want to use them?

David

--
David A. Black
dblack@wobblini.net

I want to say things like evil.rb code can write to "evil.log" but to
nothing else.
How can use threads to say this kind of things with threads?

Since you don't want to use $SAFE, the answer really is:

There is no pretty prepackaged way to do what you want to do. You can
certainly try writing it yourself, and good luck with that if you do, but a
solution using $SAFE is the only thing that will get you close to what you
want in the short term.

Kirk Haines

···

On Saturday 08 October 2005 10:01 am, aurelianito wrote:

I want to say things like evil.rb code can write to "evil.log" but to
nothing else.
How can use threads to say this kind of things with threads?