Save the world from evil code crusade

A

aurelianito

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.
 
J

James Britt

aurelianito said:
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
 
K

Kevin Brown

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.
 
A

aurelianito

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.
 
A

aurelianito

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.
 
T

ts

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

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


Guy Decoux
 
A

aurelianito

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.
 
D

David A. Black

Hi --

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
:)

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


David
 
A

aurelianito

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?
 
K

Kirk Haines

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
 
A

aurelianito

I want to say things like evil.rb code can write to "evil.log" but to
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

That's why I've started the securedruby project
(http://securedruby.rubyforge.org). My problem is that I'm unable to
stop "evil code" to modify already defined classes. The idea of the
library (already only vaporware) is to redefine all the potentially
dangerous operations in the core library to check for permissions. But
I'm unable to add this check to method redefinition. That's why I've
started two threads on this group (this one and "method added hook").

Do you know how can I achieve it (prevent class modification in some
situations)?

Aureliano.
 
J

Joel VanderWerf

aurelianito said:
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?

require 'thread'

write_queue = Queue.new

safe_thread = Thread.new do
$SAFE = 4
data = "some data"
write_queue << data
end


write_thread = Thread.new do
loop do
data = write_queue.pop
puts data # or write to "evil.log"
end
end

sleep 0.1
 
J

Joel VanderWerf

Joel said:
require 'thread'

write_queue = Queue.new

safe_thread = Thread.new do
$SAFE = 4
data = "some data"
write_queue << data
end


write_thread = Thread.new do
loop do
data = write_queue.pop

If you have no control over this data object, you probably want to check
that it really is a String (and not some spoofed string with a dangerous
#to_s method).
 
A

aurelianito

require 'thread'

write_queue = Queue.new

safe_thread = Thread.new do
$SAFE = 4
data = "some data"
write_queue << data
end


write_thread = Thread.new do
loop do
data = write_queue.pop
puts data # or write to "evil.log"
end
end

sleep 0.1

I would like to be able to write standard ruby code to do it. I mean,
use File to open a file and that's it.
I want to state the capabilities in a declarative way:
evil.rb can only write evil.log
good_and_dumb.rb can write everything.
another_even_more_evil.rb can't write anything anywhere.

And I want to be able to write this code:

good_and_dumb.rb:
require 'evil'
require 'another_even_more_evil'

a = method_defined_in_evil()
b = method_defined_in_another_even_more_evil( a )
puts b

And take no security risks. It's a difficult project, but I think it's
a good way to learn the ruby internals.

I hope this stops people from suggesting clever hacks (like the one you
just made). It's not about the clever hack. It's about how do I declare
it properly and enforce it.

Thank's for your time, and your patience,
Aureliano.
 
D

David A. Black

Hi --

I hope this stops people from suggesting clever hacks (like the one you
just made). It's not about the clever hack. It's about how do I declare
it properly and enforce it.

Don't worry -- I'm sure it will stop a number of people from
continuing to try to help you.


David
 
A

aurelianito

I hope this stops people from suggesting clever hacks (like the one you
Don't worry -- I'm sure it will stop a number of people from
continuing to try to help you.

What I've tried to say is that I want to be able to declare the
security in other way. The way I want to do it is much more granular
and declarative. I'm not looking for a way to actually implement
evil.rb. I take it as it it is and stop it to do things than I don't
want to. That's a different security model.

I'm really sorry if I offended you. That's not my intention and please
take my apologies. I'll try to write things in a way that I don't
offend any one else.

Aureliano.
 
D

David A. Black

Hi --

What I've tried to say is that I want to be able to declare the
security in other way. The way I want to do it is much more granular
and declarative. I'm not looking for a way to actually implement
evil.rb. I take it as it it is and stop it to do things than I don't
want to. That's a different security model.

I'm really sorry if I offended you. That's not my intention and please
take my apologies. I'll try to write things in a way that I don't
offend any one else.

It's OK -- I just think you may find that whatever you end up doing is
going to be a clever hack anyway, so don't necessarily discard all of
them :)

I wonder actually whether you will have to write a sort of pre-parser,
and check the code itself, and then eval it. And then of course
create some configurable way to do this.

If you do, I guess it would be "do not allow" by default -- so that if
someone tried to sneak in something bad (by doing some kind of
scrambling or method renaming or something), it would just be ignored.


David
 
R

Robert Klemme

aurelianito said:
What I've tried to say is that I want to be able to declare the
security in other way. The way I want to do it is much more granular
and declarative. I'm not looking for a way to actually implement
evil.rb. I take it as it it is and stop it to do things than I don't
want to. That's a different security model.

I'm really sorry if I offended you. That's not my intention and please
take my apologies. I'll try to write things in a way that I don't
offend any one else.

After reading the whole thread I still have two questions:

1. What exactly will your security model look like? I'm not even sure that
you have a clear vision yet so maybe before dealing with implementations it
might be more helpful to first make clear what will be allowed, what not and
how you want to separate areas of different capabilities.

2. When 1 is answered this one might become more clear: what security you
need is not possible using threads with different $SAFE levels?

Kind regards

robert
 
D

Devin Mullins

aurelianito said:
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. :) 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.
 

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
473,772
Messages
2,569,591
Members
45,103
Latest member
VinaykumarnNevatia
Top