Save the world from evil code crusade

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?

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

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

> 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

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.

Joel VanderWerf wrote:

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?

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

···

    puts data # or write to "evil.log"
  end
end

sleep 0.1

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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

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.

Hi --

···

On Sun, 9 Oct 2005, aurelianito wrote:

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

--
David A. Black
dblack@wobblini.net

Maybe there is something to learn from .NET.

Regards,
Martin

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?

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.

Setting up a list of "unsafe" methods (blacklisting) is likely to
break when more methods are added. Instead, I'd set up a list of
*safe* methods (whitelisting).

For the unsafe code part, I'd use safemode and proxy over the classes
you want to allow by overriding the MyClass constant with a pure
method_missing based proxy. The proxyied calls can be filtered for
security on the "outside", where only your code runs.

Eivind.

···

On 10/8/05, aurelianito <aurelianocalvo@yahoo.com.ar> 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?
>
> 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.
>
>

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.

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

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.

Maybe there is something to learn from .NET.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/ht
ml/cpconintroductiontocodeaccesssecurity.asp

What, not to use it? :smiley:

*ducks*

···

On Sunday 09 October 2005 06:13, Martin Honermeyer wrote:

Regards,
Martin

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

Yes! I want to implement in ruby something like this. The description
there is a copy of the Java security manager.

···

Maybe there is something to learn from .NET.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconintroductiontocodeaccesssecurity.asp

Regards,
Martin

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

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

Setting up a list of "unsafe" methods (blacklisting) is likely to
break when more methods are added. Instead, I'd set up a list of
*safe* methods (whitelisting).

I agree. But my idea is to leave security configuration to the
administrator. I want to give him/her the tools necesary to disable
unwanted behaviour.

For the unsafe code part, I'd use safemode and proxy over the classes
you want to allow by overriding the MyClass constant with a pure
method_missing based proxy. The proxyied calls can be filtered for
security on the "outside", where only your code runs.

I'm interested with this option. How do you avoid the unsafe code to
bypass the proxy? can you show me some ruby (pseudo)code?

Thank's,
Aureliano.

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.

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

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

···

On Sun, 9 Oct 2005, aurelianito wrote:

--
David A. Black
dblack@wobblini.net

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

···

aurelianito <aurelianocalvo@yahoo.com.ar> wrote:

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.

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.

> Setting up a list of "unsafe" methods (blacklisting) is likely to
> break when more methods are added. Instead, I'd set up a list of
> *safe* methods (whitelisting).

I agree. But my idea is to leave security configuration to the
administrator. I want to give him/her the tools necessary to disable
unwanted behaviour.

Same goes for the sysadmin, really. Security researchers tend to list
the use of blacklisting instead of whitelisting as one of the top five
reasons for the amounts of security problems we have.

One thing that I've personally been thinking a bit about for possible
use in FreeBSD is the ability to restrict a process to a completely
specified set of capabilities, throwing away the rest. Then, we'd
only need to trust the code that throw away the privs, not the rest.
If done conveniently, this could be used by all programs, for internal
compartmentization. This might be a different use for your code that
you've not yet thought of?

> For the unsafe code part, I'd use safemode and proxy over the classes
> you want to allow by overriding the MyClass constant with a pure
> method_missing based proxy. The proxyied calls can be filtered for
> security on the "outside", where only your code runs.

I'm interested with this option. How do you avoid the unsafe code to
bypass the proxy? can you show me some ruby (pseudo)code?

If you've wiped everything, there's no bypass possibilities (Ruby
object refs work as capabilities.) I'd probably implement this with
$SAFE = 4 for extra safety, though. Unfortunately, I lack the time to
play around with this and try to give you any decent form of code
right now.

Eivind.

···

On 10/10/05, aurelianito <aurelianocalvo@yahoo.com.ar> wrote:

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.

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

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.

One major problem when checking code is that checking names is not sufficient. IMHO you cannot solve this by changing the Ruby interpreter because you must trap into method calls for certain classes (File and Socket come to mind) and check which binary method actually gets called. And that doesn't even deal with user defined C extensions - I gues you would have to prohibit them altogether.

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.

Although I agree from a security perspective that could mean that extensibility and maybe user defined classes suffer...

Regards

    robert

···

David A. Black <dblack@wobblini.net> wrote:

On Sun, 9 Oct 2005, aurelianito wrote:

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.

A permission is an object with the method implies?( permission )

implies?( permission ) returns true iff self implies permission. For
instance:

TRUE == write_in_any_file.implies?( write_in_foo_txt ).
FALSE == write_in_any_file.implies?( format_hard_disk ).

Of course, TRUE == a.implies( a ).

When a protected operation is tried, the method am_i_allowed?(
permission ) is executed. This method returns FALSE if the "current
permissions" do not imply permission.

Each source code file will be asociated with a permission. The current
permission is the AND of the implies of the permissions of all the
files in the calling stack.

For instance.
Lets imagine:
a.rb: has format_hard_disk && write_in_any_file permissions (*).
b.rb: has write_in_any_file permission (*).

(*) assume that the ruby process is running as root for a moment.

And this is the (pseudo)code:
a.rb:
def foo()
  format_hard_disk()
end

b.rb:
require "a"
require "securedruby"
configure_permissions()
foo()

When "ruby b.rb" is run. The following process happens:
1 - foo is defined.
2 - Secured ruby is loaded.
3 - permissions for the files are set.
4 - foo is started. (STACK: b.rb, a.rb)
4.1 - format_hard_disk is started (STACK: b.rb - a.rb - ???).
4.2 - check if b.rb permissions imply format_hard_disk. (pass)
4.3 - check if a.rb permissions imply format_hard_disk. (NO pass)
4.4 - throw security exception (formatting is NOT EXECUTED).

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

That one is easy. Run untrusted libs/servlets/scripts without
modification and be able to box them without requiring the client code
to be any different as it would be if it's trusted.

Regards and thank's for your time and attention,
Aureliano.

PS: just having this conversation with all of you is making clearer for
me the picture of what I want to do. Thank you very much.

Has anyone in this thread seen E? I get the feeling that a capability based security model could be retrofitted onto ruby with some (a lot of) work. Here's one possible way I can see of doing it

All methods that allocate / initialize new objects would not return the object. Instead they would return a "name" some kind of unique symbol (generated ala gen_sym in lisp). There would then be some kind of object that kept track of the name -> object mappings. This leaves you with 1 object to audit and secure instead of hundreds. You then provide some mechanism for objects to have capabilities granted to them. You would grant capabilites to objects, NOT "name"s. The name would have a reference this master mapping object. the master mapping object would nto have any way to change what object was pointed to by what name. Any mehtod called on a "name" would turn into master_object["name"].check_capabilites_and_send(meth_sym, *args)
The result objects of this call would be another "name" again. You'd never get back the actual object you were working with so even if you hacked "name" to add evil methods it wouldn't matter since you can't send any message directly to the referenced object. You can't even get a reference to it. I leave implementing this as an exercise to the reader :wink:

One major problem when checking code is that checking names is not
sufficient. IMHO you cannot solve this by changing the Ruby interpreter
because you must trap into method calls for certain classes (File and Socket
come to mind) and check which binary method actually gets called. And that
doesn't even deal with user defined C extensions - I gues you would have to
prohibit them altogether.

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.

Although I agree from a security perspective that could mean that
extensibility and maybe user defined classes suffer...

Could a SeLinux sandbox (or binding) work?

I've never used SE Linux, so my suggestion may be dumb.

+--- Kero ------------------------- kero@chello@nl ---+

all the meaningless and empty words I spoke |
                      Promises -- The Cranberries |

+--- M38c --- http://members.chello.nl/k.vangelder ---+

aurelianito wrote:
...

a.rb:
def foo()
  format_hard_disk()
end

b.rb:
require "a"
require "securedruby"

These two lines in b.rb should be in the reverse order, shouldn't they?
How else would you protect against an a.rb lke this:

···

def foo()
  format_hard_disk()
end
format_hard_disk()

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

aurelianito wrote:
...

Each source code file will be asociated with a permission. The current
permission is the AND of the implies of the permissions of all the
files in the calling stack.

The call stack would not be enough. Another .rb file might have been
required or loaded, and it (or a method defined in it) may have done
something that allows a method called later to violate its permissions.
For example, the required file might open a file at an insecure
location. The method that did this may no longer be on the stack when
the file is written to (assuming permissions allow writing to an already
open file handle).

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407