Forum: Ruby Ruby tainting on primitives

Posted by Nicolas V. (nicolas_v)
on 2013-03-20 04:18
Hi there,

I am trying to use tainting on Ruby primitives, but it seems to be
difficult:

~ (main) > x = 123
=> 123
~ (main) > x.taint
=> 123
~ (main) > x.tainted?
=> false
~ (main) > x = 999999999999999999999999999999999
=> 999999999999999999999999999999999
~ (main) > x.taint
=> 999999999999999999999999999999999
~ (main) > x.tainted?
=> true
~ (main) >

Fixnum doesn't allow to be tainted, but Bignums are.
I was wondering if we could upgrade Fixnums into Bignums whenever they
get tainted.
In other words, I'd like automatic boxing on primitives when tainting is
used.
Posted by Hans Mackowiak (hanmac)
on 2013-03-20 07:25
that was fixed in 2.0 or 2.1dev at there Fixnums and Bignums are now 
frozen and cant be tainted or untrusted anymore (they also cant hold 
instance variables anymore)
Posted by Nicolas V. (nicolas_v)
on 2013-03-20 08:23
Maybe I was not clear.

I actually *want* to be able to taint numbers (and also booleans).
Ruby makes numbers and booleans behave like instances of classes, and so 
I would expect tainting to work normally (in some ways, the abstraction 
is leaking).
Posted by Hans Mackowiak (hanmac)
on 2013-03-20 08:30
it does not work because this primitives are instances of Classes, but 
on the C side they does not have a Struct that hold this information ...

so tainting or untrusting does not work. (ok for some reason you can 
freeze boolean, but i dont know why)
Posted by Robert Klemme (robert_k78)
on 2013-03-20 09:11
(Received via mailing list)
On Wed, Mar 20, 2013 at 8:23 AM, Nicolas V. <lists@ruby-forum.com> 
wrote:
> Maybe I was not clear.
>
> I actually *want* to be able to taint numbers (and also booleans).
> Ruby makes numbers and booleans behave like instances of classes, and so
> I would expect tainting to work normally (in some ways, the abstraction
> is leaking).

What would be the point in tainting numbers?  Numbers are immutable
anyway (well, you can set instance variables but that won't change
their behavior).  Also, since Fixnums are singletons tainting would
affect all locations - not likely that you would want that.

Kind regards

robert
Posted by Nicolas V. (nicolas_v)
on 2013-03-20 18:35
I'd like to use tainting to keep track of some data moving around.

The fact that numbers are immutable isn't really relevant. The fact that 
they're immutable doesn't necessitate they be singletons.

I realize that Fixnums are implemented as singletons as an optimization, 
but that's an implementation detail that shouldn't change the behavior 
of tainting. Ruby abstracts the implementation of Fixnums in other ways. 
For example, running `123.class` suggests that 123 is an instance of 
Fixnum. I don't understand why tainting should be different.
Posted by Robert Klemme (robert_k78)
on 2013-03-20 18:51
(Received via mailing list)
On Wed, Mar 20, 2013 at 6:35 PM, Nicolas V. <lists@ruby-forum.com> 
wrote:
> I'd like to use tainting to keep track of some data moving around.
>
> The fact that numbers are immutable isn't really relevant. The fact that
> they're immutable doesn't necessitate they be singletons.

But they are singletons.  That is a fact.

> I realize that Fixnums are implemented as singletons as an optimization,
> but that's an implementation detail that shouldn't change the behavior
> of tainting.

It doesn't.  But tainting is associated with the instance.  Hence if
you taint 0 all empty Arrays and Hashes will return a tainted 0 as
result of #size.  That doesn't make sense at all.  It also won't help
you with tracking "data moving around".

> Ruby abstracts the implementation of Fixnums in other ways.
> For example, running `123.class` suggests that 123 is an instance of
> Fixnum. I don't understand why tainting should be different.

See above.

Cheers

robert
Posted by Nicolas V. (nicolas_v)
on 2013-03-20 23:41
I understand now that we cannot taint Fixnums in the current Ruby 
implementations.

My question is whether there is an inherent conceptual reason not to 
support this behavior based on the language model Ruby tries to provide. 
You said that tainting Fixnums is not possible because Fixnums because 
they are implemented as singletons for performance reasons. But this is 
an implementation detail, not something that's part of the language 
model.

Let me formulate it like this: if I wrote a patch for Ruby to support 
tainting Fixnums with no performance overhead, would you accept it, or 
do you think tainting Fixnums semantically does not make sense? If not, 
why?
Posted by Ryan Davis (Guest)
on 2013-03-21 01:00
(Received via mailing list)
On Mar 20, 2013, at 15:41 , "Nicolas V." <lists@ruby-forum.com> wrote:

> Let me formulate it like this: if I wrote a patch for Ruby to support
> tainting Fixnums with no performance overhead, would you accept it, or
> do you think tainting Fixnums semantically does not make sense? If not,
> why?

Is there a practical reason to taint a number? Is there something I'm 
not getting?
Posted by Robert Klemme (robert_k78)
on 2013-03-21 10:17
(Received via mailing list)
On Wed, Mar 20, 2013 at 11:41 PM, Nicolas V. <lists@ruby-forum.com> 
wrote:
> I understand now that we cannot taint Fixnums in the current Ruby
> implementations.
>
> My question is whether there is an inherent conceptual reason not to
> support this behavior based on the language model Ruby tries to provide.
> You said that tainting Fixnums is not possible because Fixnums because
> they are implemented as singletons for performance reasons. But this is
> an implementation detail, not something that's part of the language
> model.

It may be an implementation detail in other contexts but when it comes
to attaching state to a singleton it is an important feature because
all users of the singleton will be affected.

> Let me formulate it like this: if I wrote a patch for Ruby to support
> tainting Fixnums with no performance overhead, would you accept it, or
> do you think tainting Fixnums semantically does not make sense? If not,
> why?

I would not accept it because of the unwanted side effects.  I have
explained that in my previous posting.  Since you did not react to it
I have no idea whether you read or understood it.  If not, please do.

Cheers

robert
Posted by Nicolas V. (nicolas_v)
on 2013-03-21 10:34
We would preserve all the semantics. Let me explain.

For example, when the user tries to taint a Fixnum, instead of throwing 
a freeze error, we would upgrade the Fixnum into a Bignum.
In other words, we can box primitives when the user tries to taint.
Tainted numbers would obviously have a performance hit due to the 
unboxing, but I don't expect performance regressions for code that does 
not taint Fixnums.
Posted by Hans Mackowiak (hanmac)
on 2013-03-21 10:45
did you image how to "upgrade the Fixnum into a Bignum."?

it does not make sense, cause the world of Integer is parted ... little 
ones are Fixnum, big ones are Bignum.

you cant "upgrade" them so that you get an Bignum with the same value as 
a fixnum, you need a Holder Class for that, and if you use a 
HolderClass, you already have something that can be tainted
Posted by Nicolas V. (nicolas_v)
on 2013-03-21 11:00
Hans Mackowiak wrote in post #1102567:
> did you image how to "upgrade the Fixnum into a Bignum."?
Fair enough, I was wrong.

>
> it does not make sense, cause the world of Integer is parted ... little
> ones are Fixnum, big ones are Bignum.
>
> you cant "upgrade" them so that you get an Bignum with the same value as
> a fixnum, you need a Holder Class for that, and if you use a
> HolderClass, you already have something that can be tainted

Which brings me to this point. I think it would be nice if we could use 
Bignum as HolderClass for Fixnum. For example, `123.to_fixnum` would 
return a Bignum of value 123. Operations involving a tainted Bignum 
would preserve the semantics. For example with an addition: 
BignumTainted + Fixnum -> BignumTainted.

Would it be preferable to implement that HolderClass in userland? or in 
Ruby?
Posted by Ryan Davis (Guest)
on 2013-03-22 01:35
(Received via mailing list)
On Mar 21, 2013, at 02:34 , Nicolas V. <lists@ruby-forum.com> wrote:

> We would preserve all the semantics. Let me explain.

Which gets you ... what?

Tainting a number makes no sense to me. You can't use it as an attack 
vector. You can't get it from a socket. You can't get it from a file. 
Basically... to get a number, you've already untainted it at some point. 
The only place I can think of where you can get a number from an 
external resource is via marshal or some other marshalling format. If it 
is already compromised, you've got other problems.
Posted by Nicolas V. (nicolas_v)
on 2013-03-22 01:53
That is actually where I'm coming from. Some JSON is coming from an 
external source, and I would like to track the parsed content.

The default JSON parser has its own set of problems:

(main) > json = '{"key":"value"}';
(main) > json.taint
=> "{\"key\":\"value\"}"
(main) > json.tainted?
=> true
(main) > JSON.parse(json).tainted?
=> false
(main) > JSON.parse(json)['key'].tainted?
=> false

Assuming this is easily fixable, I would like to track the parsed data, 
especially numbers.

I don't use tainting to achieve some level of security, but to perform 
various optimization in a distributed algorithm.
Posted by Ryan Davis (Guest)
on 2013-03-22 02:01
(Received via mailing list)
On Mar 21, 2013, at 17:53 , Nicolas V. <lists@ruby-forum.com> wrote:

> I don't use tainting to achieve some level of security, but to perform
> various optimization in a distributed algorithm.

which is not what tainting is for.
Posted by Nicolas V. (nicolas_v)
on 2013-03-22 02:05
Ryan Davis wrote in post #1102698:
> On Mar 21, 2013, at 17:53 , Nicolas V. <lists@ruby-forum.com> wrote:
>
>> I don't use tainting to achieve some level of security, but to perform
>> various optimization in a distributed algorithm.
>
> which is not what tainting is for.

Oh wow.

I am going out of the discussion,
Thanks.
Posted by Joel Pearson (virtuoso)
on 2013-03-22 09:57
Wouldn't it be simpler to create a custom class with an attribute that 
covers this? I should think that using taint just to track numbers could 
have nasty side effects if your program expanded later.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.