New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mass assignment vulnerability - how to force dev. define attr_accesible? #5228

Closed
homakov opened this Issue Mar 1, 2012 · 106 comments

Comments

Projects
None yet
@homakov
Contributor

homakov commented Mar 1, 2012

Those who don't know methods attr_accesible / protected - check that article out http://enlightsolutions.com/articles/whats-new-in-edge-scoped-mass-assignment-in-rails-3-1

Let's view at typical situation - middle level rails developer builds website for customer, w/o any special protections in model(Yeah! they don't write it! I have asked few my friends - they dont!)
Next, people use this website but if any of them has an idea that developer didnt specify "attr_accesible" - hacker can just add an http field in params, e.g. we have pursue's name edition. POST request at pursues#update

id = 333 (target's pursues id)
pursue['name'] = 'my purses name'
pursue['user_id'] = 412(hacker id)

if code is scaffolded than likely we got Pursue.find(params[:id]).update_attributes(params[:pursue]) in the controller. And that is what I worry about.

After execution that POST we got hacker owning target's pursue!

I don't mean that it is Rails problem, of course not. But let's get it real(Getting Real ok) - most of developers are middle/junior level and most of them don't write important but not very neccessary things: tests, role checks etc including topic - attr_accesible

how to avoid injections ? What should Rails framework do to force people to keep their rails websites safe? Making attr_accesible necessary field in model? What do you think guys.

@drogus

This comment has been minimized.

Show comment
Hide comment
@drogus

drogus Mar 1, 2012

Member

I was thinking about generating something like this, unless you pass some kind of option to generator (sometimes you just want to skip attr_accessible if you know what you're doing):

# You should always whitelist your accessible attributes for security
attr_accessible nil
Member

drogus commented Mar 1, 2012

I was thinking about generating something like this, unless you pass some kind of option to generator (sometimes you just want to skip attr_accessible if you know what you're doing):

# You should always whitelist your accessible attributes for security
attr_accessible nil
@drogus

This comment has been minimized.

Show comment
Hide comment
@drogus

drogus Mar 1, 2012

Member

@lest pointed me to #4062, there is a config setting that can do something like that config.active_record.whitelist_attributes. Although, based on that discussion I think that the consensus is that it should not be the default.

Member

drogus commented Mar 1, 2012

@lest pointed me to #4062, there is a config setting that can do something like that config.active_record.whitelist_attributes. Although, based on that discussion I think that the consensus is that it should not be the default.

@drogus drogus closed this Mar 1, 2012

@drogus drogus reopened this Mar 1, 2012

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 1, 2012

Contributor

so, here is what i came up to.
My main concern - is relations.
I hate the idea that some people could rewrite object references by themselves. Nobody should be able to set task[user_id]=hacker_id or sort of
Vulnerable references are the main evil because

  1. it totally ruins database and leaves no way to fix it back but backups
  2. it works clearly. Hacked user won't be able to figure out "Where is my blog post" or "How come this spam post is in my timeline written by me" (if newpost[user_id]=target_user_to_hack)

I suggest to have foreign keys and primary keys protected by default(what are keys can be recognized by ActiveRecord easily).

IMO Rails should teach developers to set up so important and vulnerable keys by hands. It is not a handicap for prototyping, just +a few lines of code. But it is all about sane and safe rails apps.

@task = Task.new
@task.user = current_user
@task.update_attributes(params[:task]) #having params[:task][:user_id] should raise error

#or projects-tasks relations
@project = Project.find(params.delete(:project_id)) #we have project_id but it is protected. lets delete to avoid exception
if @project.user == current_user
  @task.project = @project
else
  #alarm!
end
@task.attributes = params[:task]

I've got a big picture in my head but the backbone is described above. I strongly believe that having keys(references, relations) will make ruby on rails a 20% more awesome. I mean robust

Contributor

homakov commented Mar 1, 2012

so, here is what i came up to.
My main concern - is relations.
I hate the idea that some people could rewrite object references by themselves. Nobody should be able to set task[user_id]=hacker_id or sort of
Vulnerable references are the main evil because

  1. it totally ruins database and leaves no way to fix it back but backups
  2. it works clearly. Hacked user won't be able to figure out "Where is my blog post" or "How come this spam post is in my timeline written by me" (if newpost[user_id]=target_user_to_hack)

I suggest to have foreign keys and primary keys protected by default(what are keys can be recognized by ActiveRecord easily).

IMO Rails should teach developers to set up so important and vulnerable keys by hands. It is not a handicap for prototyping, just +a few lines of code. But it is all about sane and safe rails apps.

@task = Task.new
@task.user = current_user
@task.update_attributes(params[:task]) #having params[:task][:user_id] should raise error

#or projects-tasks relations
@project = Project.find(params.delete(:project_id)) #we have project_id but it is protected. lets delete to avoid exception
if @project.user == current_user
  @task.project = @project
else
  #alarm!
end
@task.attributes = params[:task]

I've got a big picture in my head but the backbone is described above. I strongly believe that having keys(references, relations) will make ruby on rails a 20% more awesome. I mean robust

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 1, 2012

Contributor

Oh, didn't mention. On my part - I wouldn't support setting all attrs protected. It will cause such big mess! You cannot force every body to read release notes. Stackoverflow will be down. :] + it is dirty solution.
What also we have in model but keys? E.g.
title: string - not vulnerable at all, user is able to edit his comment
rating: integer - pretty vulnerable but not dangerous
account: integer - developer who left user[account] open for mass assignment should suffer. Nevermind about him.
what else? Do we really need protected fields by default? No.

Contributor

homakov commented Mar 1, 2012

Oh, didn't mention. On my part - I wouldn't support setting all attrs protected. It will cause such big mess! You cannot force every body to read release notes. Stackoverflow will be down. :] + it is dirty solution.
What also we have in model but keys? E.g.
title: string - not vulnerable at all, user is able to edit his comment
rating: integer - pretty vulnerable but not dangerous
account: integer - developer who left user[account] open for mass assignment should suffer. Nevermind about him.
what else? Do we really need protected fields by default? No.

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 1, 2012

Contributor

@dhh you dont like 'whitelist' idea - i dont too. But what is your opinion regards relation keys? They are obviously should be defined manually - in most cases. That is why having them protected by default is not a big deal.
And, surely, it should be opt-out-able, e.g.
config.active_record.protect_keys = true

Contributor

homakov commented Mar 1, 2012

@dhh you dont like 'whitelist' idea - i dont too. But what is your opinion regards relation keys? They are obviously should be defined manually - in most cases. That is why having them protected by default is not a big deal.
And, surely, it should be opt-out-able, e.g.
config.active_record.protect_keys = true

@homakov homakov referenced this issue Mar 2, 2012

Closed

3012 #5239

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 2, 2012

Contributor

Just imagine which power this vulnerability gives in my.. and now in your hands if you get what has happened.
@dhh @josevalim Y you no care :trollface:

Contributor

homakov commented Mar 2, 2012

Just imagine which power this vulnerability gives in my.. and now in your hands if you get what has happened.
@dhh @josevalim Y you no care :trollface:

@sikachu

This comment has been minimized.

Show comment
Hide comment
@sikachu

sikachu Mar 2, 2012

Member

There're too much trolling going on in this ticket and I'm not sure anymore if you mean anything serious. If you're going to do a bug report or feature request, just stop trolling and try not to be annoying, then the core team will come and check out by themselves.

Name calling while trolling doesn't help, trust me.

Member

sikachu commented Mar 2, 2012

There're too much trolling going on in this ticket and I'm not sure anymore if you mean anything serious. If you're going to do a bug report or feature request, just stop trolling and try not to be annoying, then the core team will come and check out by themselves.

Name calling while trolling doesn't help, trust me.

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 2, 2012

Contributor

@sikachu bugs are serious.

This is not only bug report, because this problem is so wide spreaded. postereous, speakerdeck, scribd, github - and I only have started testing.

We need to introduce blacklist attributes. MOst of rails apps(from small to github) likely got mass-assignment bugs if they don't user attr_accessible.

I just want to attract more attention to reviewing this problem from scratch and calmly decide - what should we do with M As-ment problem.

And, if some of you support my idea I could provide fixing pull request. But you ignore this bug, like nothing has happened for a long time. SOrry for not called for trolling, I overplayed :) Everyone, again, express your point please, you are welcome.

Contributor

homakov commented Mar 2, 2012

@sikachu bugs are serious.

This is not only bug report, because this problem is so wide spreaded. postereous, speakerdeck, scribd, github - and I only have started testing.

We need to introduce blacklist attributes. MOst of rails apps(from small to github) likely got mass-assignment bugs if they don't user attr_accessible.

I just want to attract more attention to reviewing this problem from scratch and calmly decide - what should we do with M As-ment problem.

And, if some of you support my idea I could provide fixing pull request. But you ignore this bug, like nothing has happened for a long time. SOrry for not called for trolling, I overplayed :) Everyone, again, express your point please, you are welcome.

@fxn

This comment has been minimized.

Show comment
Hide comment
@fxn

fxn Mar 2, 2012

Member

There was a proposal about changing that flag in #4062 and the consensus is the pros of the default configuration outweigh the pros of the alternative.

Thanks!

Member

fxn commented Mar 2, 2012

There was a proposal about changing that flag in #4062 and the consensus is the pros of the default configuration outweigh the pros of the alternative.

Thanks!

@fxn fxn closed this Mar 2, 2012

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 2, 2012

Contributor

@fxn have you read my post? Did you see vulnerabilities i pointed out in e.g. github?
It is not about the flag in configuration, I'm pretty certain. We need to have :created_at, :updated_at, and references to be protected by default. Whitelist issue has nothing to do with my point
Please read issues carefully, because I clearly emphysized that flag is not a panacea

Contributor

homakov commented Mar 2, 2012

@fxn have you read my post? Did you see vulnerabilities i pointed out in e.g. github?
It is not about the flag in configuration, I'm pretty certain. We need to have :created_at, :updated_at, and references to be protected by default. Whitelist issue has nothing to do with my point
Please read issues carefully, because I clearly emphysized that flag is not a panacea

@fxn

This comment has been minimized.

Show comment
Hide comment
@fxn

fxn Mar 2, 2012

Member

What I want you to see in that thread I mentioned is the way the core team perceives this. You are not discovering anything unknown, we already know this stuff and we like attr protection to work the way it is.

Member

fxn commented Mar 2, 2012

What I want you to see in that thread I mentioned is the way the core team perceives this. You are not discovering anything unknown, we already know this stuff and we like attr protection to work the way it is.

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 2, 2012

Contributor

look. this is github, written on rails. https://github.com/homakov/ClientSit/issues/4
as you see github is vulnerable. Because gh devs are bad? Or who's in charge?
Rails are in charge, and blacklist of custom [:created_ate, :updated_at] is the least we MUST do

Really, is there any case when user should be able set created_at by himself? It is timestamp! Why I can set it using just <input name=model[created_at] value='1987...' ?
Again, let's talk about certain vulnerability-case. :created_at MUST be protected by default. Am i right?

Contributor

homakov commented Mar 2, 2012

look. this is github, written on rails. https://github.com/homakov/ClientSit/issues/4
as you see github is vulnerable. Because gh devs are bad? Or who's in charge?
Rails are in charge, and blacklist of custom [:created_ate, :updated_at] is the least we MUST do

Really, is there any case when user should be able set created_at by himself? It is timestamp! Why I can set it using just <input name=model[created_at] value='1987...' ?
Again, let's talk about certain vulnerability-case. :created_at MUST be protected by default. Am i right?

@fxn

This comment has been minimized.

Show comment
Hide comment
@fxn

fxn Mar 3, 2012

Member

Rails is not in charge, it is your responsibility to secure your application. It is your responsibility to avoid XSS, to ensure that the user is editing a resource that belongs to him, etc.

Rails, however, does a lot of effort to assist you in securing your application as much as it can. That's why you have some protection measures built-in.

I don't think we need to special-case anything. The user has a flag to secure by default, I personally think that is enough. I see little benefit in special-casing the timestamps if you have the flag set to false. And I am totally -1 in doing anything fancy with foreign keys because they have of course valid use cases where users can set them.

Member

fxn commented Mar 3, 2012

Rails is not in charge, it is your responsibility to secure your application. It is your responsibility to avoid XSS, to ensure that the user is editing a resource that belongs to him, etc.

Rails, however, does a lot of effort to assist you in securing your application as much as it can. That's why you have some protection measures built-in.

I don't think we need to special-case anything. The user has a flag to secure by default, I personally think that is enough. I see little benefit in special-casing the timestamps if you have the flag set to false. And I am totally -1 in doing anything fancy with foreign keys because they have of course valid use cases where users can set them.

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 3, 2012

Contributor

Perfect response. Rails are not in charge - my question was like, 'why is that'. Surely nobody is fully in charge.

But only rails apps got this kind of bug. Yeah, phpists never got so fast prototyping tools so most of them cannot even dream about update_attributes {} and form generation too.

Rails has very convinient tools, I agree! attr_accessible is good and must thing for every developer. But for now we got it too unknown. Most of middle level developers forget about the meaning of this tool. Mixes with attr_accessors in ruby itself - so their model gets very unsecure.

So you only a little bit support special casing of timestamp.
For first view at the problem of timestamp-overwriting it doesn't seem fatal. But when I have issue/comment written in 3012 year I at least have it number 1 in any timeline orders. That seems ugly to me so I am keen to special case timestamps.

Regards foreign keys - I didn't get why you are "totally" -1, and if you got spare time please give me valid use cases if you know some. That will help me in understanding your point fully

another way to decide problem - populate using of accessible. Include it in scaffold generated output for model files. Im pretty sure rubyists will care much more having these lines and one day 4/5 will know+use this declaration. (now 4/5 don't either know or use, that's sad)

Contributor

homakov commented Mar 3, 2012

Perfect response. Rails are not in charge - my question was like, 'why is that'. Surely nobody is fully in charge.

But only rails apps got this kind of bug. Yeah, phpists never got so fast prototyping tools so most of them cannot even dream about update_attributes {} and form generation too.

Rails has very convinient tools, I agree! attr_accessible is good and must thing for every developer. But for now we got it too unknown. Most of middle level developers forget about the meaning of this tool. Mixes with attr_accessors in ruby itself - so their model gets very unsecure.

So you only a little bit support special casing of timestamp.
For first view at the problem of timestamp-overwriting it doesn't seem fatal. But when I have issue/comment written in 3012 year I at least have it number 1 in any timeline orders. That seems ugly to me so I am keen to special case timestamps.

Regards foreign keys - I didn't get why you are "totally" -1, and if you got spare time please give me valid use cases if you know some. That will help me in understanding your point fully

another way to decide problem - populate using of accessible. Include it in scaffold generated output for model files. Im pretty sure rubyists will care much more having these lines and one day 4/5 will know+use this declaration. (now 4/5 don't either know or use, that's sad)

@drogus

This comment has been minimized.

Show comment
Hide comment
@drogus

drogus Mar 3, 2012

Member

@homakov I also don't like the idea of doing anything automated with foreign keys or timestamps. That way, people that does not know that they need to use some kind of params protection will be secure in those 2 cases, but it will fail with any other critical field, let's say admin.

@fxn what do you think about generating a model class with a comment describing attr_accessible and giving example, something like:

# If this model can be modified by publicly available resource using update_attributes
# method, you should protect its attributes with attr_accessible, for example:
# attr_accessible :title, :body
Member

drogus commented Mar 3, 2012

@homakov I also don't like the idea of doing anything automated with foreign keys or timestamps. That way, people that does not know that they need to use some kind of params protection will be secure in those 2 cases, but it will fail with any other critical field, let's say admin.

@fxn what do you think about generating a model class with a comment describing attr_accessible and giving example, something like:

# If this model can be modified by publicly available resource using update_attributes
# method, you should protect its attributes with attr_accessible, for example:
# attr_accessible :title, :body
@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 3, 2012

Contributor

@drogus it is your viewpoint. Ok, let's not bother junior devs who will need to think about protection.
But I like your proposal regards model generator. I suggested it as an alternative, this fix will satisfy me. :)

Contributor

homakov commented Mar 3, 2012

@drogus it is your viewpoint. Ok, let's not bother junior devs who will need to think about protection.
But I like your proposal regards model generator. I suggested it as an alternative, this fix will satisfy me. :)

@rmoriz

This comment has been minimized.

Show comment
Hide comment
@rmoriz

rmoriz Mar 4, 2012

It's 2012. When will people stop believing in "blacklists"?

The default has to be restrictive and the developer has to make sure she/he does acceptable exceptions. It's like with the XSS/sanitize stuff. It will never work the "blacklist"/"developer should care" way, imho.

At least throw a warning into the debug-log when a model has no attr_accessible defined at all...

rmoriz commented Mar 4, 2012

It's 2012. When will people stop believing in "blacklists"?

The default has to be restrictive and the developer has to make sure she/he does acceptable exceptions. It's like with the XSS/sanitize stuff. It will never work the "blacklist"/"developer should care" way, imho.

At least throw a warning into the debug-log when a model has no attr_accessible defined at all...

@docwhat

This comment has been minimized.

Show comment
Hide comment
@docwhat

docwhat Mar 4, 2012

Contributor

@homakov Is this how you added b839657

Just curious.

Contributor

docwhat commented Mar 4, 2012

@homakov Is this how you added b839657

Just curious.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Mar 4, 2012

@rmoriz +1

Rails is all about conventions. Broken by default is not a good convention.

ghost commented Mar 4, 2012

@rmoriz +1

Rails is all about conventions. Broken by default is not a good convention.

@bai

This comment has been minimized.

Show comment
Hide comment
@bai

bai Mar 4, 2012

@homakov Man, you look like a kid that wants some attention. Stop trolling and make GitHub a favor — file a private bug request via contact form — that's how non-douchebag people do.

I totally agree with @fxn — missing attr_accessible is not Rails' fault but developer's mistake. Generated models could have a friendly comment like @drogus said, but in practice I think we don't use generators that much, I thought that's easier just to type class Blah < ActiveRecord::Base.

bai commented Mar 4, 2012

@homakov Man, you look like a kid that wants some attention. Stop trolling and make GitHub a favor — file a private bug request via contact form — that's how non-douchebag people do.

I totally agree with @fxn — missing attr_accessible is not Rails' fault but developer's mistake. Generated models could have a friendly comment like @drogus said, but in practice I think we don't use generators that much, I thought that's easier just to type class Blah < ActiveRecord::Base.

@docwhat

This comment has been minimized.

Show comment
Hide comment
@docwhat

docwhat Mar 4, 2012

Contributor

@bai don't shoot the messenger, dude.

Contributor

docwhat commented Mar 4, 2012

@bai don't shoot the messenger, dude.

@rmoriz

This comment has been minimized.

Show comment
Hide comment
@rmoriz

rmoriz Mar 4, 2012

@bai what you say? Every book, every tutorial, every guide tells developers to use generators. Do you create all the test + migration files by hand?!

rmoriz commented Mar 4, 2012

@bai what you say? Every book, every tutorial, every guide tells developers to use generators. Do you create all the test + migration files by hand?!

@bai

This comment has been minimized.

Show comment
Hide comment
@bai

bai Mar 4, 2012

@docwhat I might have a bit overreacted — apologies for that. Yet I think giving one example of vulnerability is enough, no need to go through commits and issues over and over screwing things up.

bai commented Mar 4, 2012

@docwhat I might have a bit overreacted — apologies for that. Yet I think giving one example of vulnerability is enough, no need to go through commits and issues over and over screwing things up.

@cmelbye

This comment has been minimized.

Show comment
Hide comment
@cmelbye

cmelbye Mar 4, 2012

@bai is right, though. Zero-day attacks are a completely inappropriate way of raising awareness of a vulnerability.

cmelbye commented Mar 4, 2012

@bai is right, though. Zero-day attacks are a completely inappropriate way of raising awareness of a vulnerability.

@bai

This comment has been minimized.

Show comment
Hide comment
@bai

bai Mar 4, 2012

@rmoriz I use generators on prototyping stage extensively, but then it simply gets too custom and often beyond scaffolds. It depends on a dev though.

bai commented Mar 4, 2012

@rmoriz I use generators on prototyping stage extensively, but then it simply gets too custom and often beyond scaffolds. It depends on a dev though.

@rmoriz

This comment has been minimized.

Show comment
Hide comment
@rmoriz

rmoriz Mar 4, 2012

@bai it's primarily a model issue, not a scaffolding issue. attr_accessor is defined inside a model, not in a controller. 100% of all developers I've worked since 2007 use generators to create models + migrations.

rmoriz commented Mar 4, 2012

@bai it's primarily a model issue, not a scaffolding issue. attr_accessor is defined inside a model, not in a controller. 100% of all developers I've worked since 2007 use generators to create models + migrations.

@mtkd

This comment has been minimized.

Show comment
Hide comment
@mtkd

mtkd Mar 4, 2012

Two security issues concern me about Rails:

  1. The defaults not being restrictive

  2. Lack of any certification for Gem distribution (imagine if someone got a commit in to some of the most popular gems)

mtkd commented Mar 4, 2012

Two security issues concern me about Rails:

  1. The defaults not being restrictive

  2. Lack of any certification for Gem distribution (imagine if someone got a commit in to some of the most popular gems)

@rmoriz

This comment has been minimized.

Show comment
Hide comment
@rmoriz

rmoriz Mar 4, 2012

@mtkd rubygems does not even have a popular self-signing implementation as most cpan modules (perl) use. So you can't be sure the gem you've downloaded is the one the author made (not the CIA or another MITM).

http://search.cpan.org/~andk/CPAN-1.9800/lib/CPAN.pm#Cryptographically_signed_modules

(cpan 1.77 was released iirc around 2002/2003)

rmoriz commented Mar 4, 2012

@mtkd rubygems does not even have a popular self-signing implementation as most cpan modules (perl) use. So you can't be sure the gem you've downloaded is the one the author made (not the CIA or another MITM).

http://search.cpan.org/~andk/CPAN-1.9800/lib/CPAN.pm#Cryptographically_signed_modules

(cpan 1.77 was released iirc around 2002/2003)

@bai

This comment has been minimized.

Show comment
Hide comment
@bai

bai Mar 4, 2012

@rmoriz RubyGems supports gem signing, I use it for a client of mine: http://docs.rubygems.org/read/chapter/21
On the other hand, 99.999% of gems don't use it :-)

bai commented Mar 4, 2012

@rmoriz RubyGems supports gem signing, I use it for a client of mine: http://docs.rubygems.org/read/chapter/21
On the other hand, 99.999% of gems don't use it :-)

@rmoriz

This comment has been minimized.

Show comment
Hide comment
@rmoriz

rmoriz Mar 4, 2012

@bai iirc only when explicitly specified on the cli (what about bundler?) and as you said...."not very well" adopted.

rmoriz commented Mar 4, 2012

@bai iirc only when explicitly specified on the cli (what about bundler?) and as you said...."not very well" adopted.

@Pewpewarrows

This comment has been minimized.

Show comment
Hide comment
@Pewpewarrows

Pewpewarrows Mar 4, 2012

In this thread: core rails devs get egg on their faces for ignoring a fundamental security concern, and then proceed to complain when the reporter 0days GitHub.

Pewpewarrows commented Mar 4, 2012

In this thread: core rails devs get egg on their faces for ignoring a fundamental security concern, and then proceed to complain when the reporter 0days GitHub.

@bai

This comment has been minimized.

Show comment
Hide comment
@bai

bai Mar 4, 2012

Rails devs are not responsible for Rails-powered sites. It's not their fault.

bai commented Mar 4, 2012

Rails devs are not responsible for Rails-powered sites. It's not their fault.

@wycats

This comment has been minimized.

Show comment
Hide comment
@wycats

wycats Mar 4, 2012

Member

See https://gist.github.com/1974187 for my proposal for how to improve the situation.

Member

wycats commented Mar 4, 2012

See https://gist.github.com/1974187 for my proposal for how to improve the situation.

@jacortinas

This comment has been minimized.

Show comment
Hide comment
@jacortinas

jacortinas Mar 4, 2012

Contributor

@bai I don't think that's completely correct, the fix presented in this issue is exactly what the Rails core devs could do, to assist the novice Rails devs. Convention over Configuration means that the Rails devs are actually partially responsible for Rails-powered sites because they establish the convention.

Contributor

jacortinas commented Mar 4, 2012

@bai I don't think that's completely correct, the fix presented in this issue is exactly what the Rails core devs could do, to assist the novice Rails devs. Convention over Configuration means that the Rails devs are actually partially responsible for Rails-powered sites because they establish the convention.

@metaskills

This comment has been minimized.

Show comment
Hide comment
@metaskills

metaskills Mar 4, 2012

Contributor

@wycats Proposal for Improving Mass Assignment - https://gist.github.com/1974187

Contributor

metaskills commented Mar 4, 2012

@wycats Proposal for Improving Mass Assignment - https://gist.github.com/1974187

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Mar 5, 2012

Contributor

@ELeo exactly. That's what I tried to say dhh in my gist. Controller has nothing to do with unintended params. It doesnt filter. It handles, manages, controls business logic.
IMO You should write your controllers way described below:

  1. have all critical fields protected/updateable - accessible
  2. control saving new record in controller using role checks, dependencies and abilities. Not just by filtering :user_id
  3. Never simplify business logic for "update". People got role checks in "create" but trying to manage just "update_attributes" in edit and that's why this has happened. If you check role - check it on create and on update.

Don't be lazy. sic!

Contributor

homakov commented Mar 5, 2012

@ELeo exactly. That's what I tried to say dhh in my gist. Controller has nothing to do with unintended params. It doesnt filter. It handles, manages, controls business logic.
IMO You should write your controllers way described below:

  1. have all critical fields protected/updateable - accessible
  2. control saving new record in controller using role checks, dependencies and abilities. Not just by filtering :user_id
  3. Never simplify business logic for "update". People got role checks in "create" but trying to manage just "update_attributes" in edit and that's why this has happened. If you check role - check it on create and on update.

Don't be lazy. sic!

@roozbehk

This comment has been minimized.

Show comment
Hide comment
@roozbehk

roozbehk Mar 5, 2012

@homakov I see your price-list updated on your site :D. With you are skills and rails knowledge, you are asking for a junior dev salary in us.

roozbehk commented Mar 5, 2012

@homakov I see your price-list updated on your site :D. With you are skills and rails knowledge, you are asking for a junior dev salary in us.

@jnevelson

This comment has been minimized.

Show comment
Hide comment
@jnevelson

jnevelson Mar 5, 2012

@ELeo, what if you protect those attributes in ActionController::Base, which all other controller inherit from? This would allow you to still set all attributes in your test cases, and you would protect against having multiple points of failure.

jnevelson commented Mar 5, 2012

@ELeo, what if you protect those attributes in ActionController::Base, which all other controller inherit from? This would allow you to still set all attributes in your test cases, and you would protect against having multiple points of failure.

@rorra

This comment has been minimized.

Show comment
Hide comment
@rorra

rorra Mar 5, 2012

Contributor

Probably you can make a branch like "rails_for_developers_that_doesnt_read_documentation" and in that branch you can take off update_attributes, and there you will have a "secure" rails framework for people complaining about this issue :)

Contributor

rorra commented Mar 5, 2012

Probably you can make a branch like "rails_for_developers_that_doesnt_read_documentation" and in that branch you can take off update_attributes, and there you will have a "secure" rails framework for people complaining about this issue :)

@egroeper

This comment has been minimized.

Show comment
Hide comment
@egroeper

egroeper Mar 5, 2012

@kalleboo +1
Exactly what I thought. This is a new register_globals.
Unbelievable.

egroeper commented Mar 5, 2012

@kalleboo +1
Exactly what I thought. This is a new register_globals.
Unbelievable.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Mar 5, 2012

FWIW, this behavior isn't unique to Rails. Or, to be more specific, it isn't unique to ActiveRecord. If you were to look at other ORMs/ODMs, such as DataMapper, Sequel, MongoMapper, or Mongoid, you could see that mass assignment was allowed by default on any given model, and can be adjusted using a whitelist (or sometimes a blacklist) class method.

I don't see anything wrong with this per se. To disallow mass assignment by default would be a safer default, but it also makes the assumption on what you're doing in your application, and what does and doesn't need to be secured from user tampering. But it also requires you to be aware of the potential security concern to begin with and be thoughtful of it when designing your models.

ghost commented Mar 5, 2012

FWIW, this behavior isn't unique to Rails. Or, to be more specific, it isn't unique to ActiveRecord. If you were to look at other ORMs/ODMs, such as DataMapper, Sequel, MongoMapper, or Mongoid, you could see that mass assignment was allowed by default on any given model, and can be adjusted using a whitelist (or sometimes a blacklist) class method.

I don't see anything wrong with this per se. To disallow mass assignment by default would be a safer default, but it also makes the assumption on what you're doing in your application, and what does and doesn't need to be secured from user tampering. But it also requires you to be aware of the potential security concern to begin with and be thoughtful of it when designing your models.

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 5, 2012

@ELeo If somebody develops an application what will be available from internet for a wide publicity, then it must be protected on all way. I wouldn't like point to GitHub issue what happens if application is not protected. You cannot trust in the internet. If you are a beginner, then read the f_ing manual to yourself, and again, and again, until you understood: the security is not an option, but a requirement for your application.

I understand some ORMs does not enforce this security setting by default but this page is not an issue page for Mongoid, Sequel, or DataMapper, but it is an issue page for Rails, or to be more specific, for ActiveRecord.. If other ORMs decide make a possible security hole on a non-careful developer's code, then this is their own decision, not the rails developers' one.
Because somebody decides he jumping from the rock without a rope, we do not need to follow that example. We can attach ourself to a rope, and we currently doing it.

hron84 commented Mar 5, 2012

@ELeo If somebody develops an application what will be available from internet for a wide publicity, then it must be protected on all way. I wouldn't like point to GitHub issue what happens if application is not protected. You cannot trust in the internet. If you are a beginner, then read the f_ing manual to yourself, and again, and again, until you understood: the security is not an option, but a requirement for your application.

I understand some ORMs does not enforce this security setting by default but this page is not an issue page for Mongoid, Sequel, or DataMapper, but it is an issue page for Rails, or to be more specific, for ActiveRecord.. If other ORMs decide make a possible security hole on a non-careful developer's code, then this is their own decision, not the rails developers' one.
Because somebody decides he jumping from the rock without a rope, we do not need to follow that example. We can attach ourself to a rope, and we currently doing it.

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 5, 2012

There was one problem with this option: it wasn't promoted enough. I never saw this option in the generated default config files, and if this (and GitHub) issue does not points me to it, I never set it, even if I use attr_accessible in my applications.

Promoting the security is a very high priority communication job, if there is one channel where we can do it, we need to do it.

hron84 commented Mar 5, 2012

There was one problem with this option: it wasn't promoted enough. I never saw this option in the generated default config files, and if this (and GitHub) issue does not points me to it, I never set it, even if I use attr_accessible in my applications.

Promoting the security is a very high priority communication job, if there is one channel where we can do it, we need to do it.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Mar 6, 2012

@hron84 You can't protect the user from everything.

Having all attributes blacklisted is arguably a safer default, as I said. It nonetheless makes assumptions about the application. There might be no need for certain applications (which might not even necessarily be "web apps" per se) to have all attributes blacklisted by default. Some users might even find such a default more burdensome than helpful, depending on what their use case is.

The irony of your "read the f_ing manual" statement is that the lack thereof is part of the problem here. Users aren't protecting their attributes either out of ignorance or oversight. And to be fair, maybe the vulnerability isn't stressed enough in the documentation. (I haven't looked.) I'm not arguing against trying to mitigate potential disaster -- I'm all for it -- but I would also argue that if one doesn't truly understand why mass assignment is disabled by default, then he or she is liable to make their models insecure no matter what.

And for the users who are truly oblivious, here's what's going to happen anyway:

"I can't set user_id from this form. Let me just add user_id to the attr_accessible array, because that's what will make this action work the way I want it to."

That user doesn't understand what attr_accessible is for, why they'd want to whitelist attributes, why they need to whitelist attributes, and what can happen if they whitelist the wrong attributes. They might not even understand that they are whitelisting attributes -- they might think attr_accessible is some kind of riff on attr_accessor that adds getters and setters based on their schema.

At best, we're really just going to make it a little more difficult for them to screw themselves. Defaulting to a blacklist is an improvement to security, but no panacea. And I guess that's what I was getting at in my previous posts. It seems like some people are mindblown by all this, like allowing you to protect your attributes but not doing it by default is just nuts. We can go ahead and improve it, but there's still a dozen other gotchas awaiting the unprepared developer.

ghost commented Mar 6, 2012

@hron84 You can't protect the user from everything.

Having all attributes blacklisted is arguably a safer default, as I said. It nonetheless makes assumptions about the application. There might be no need for certain applications (which might not even necessarily be "web apps" per se) to have all attributes blacklisted by default. Some users might even find such a default more burdensome than helpful, depending on what their use case is.

The irony of your "read the f_ing manual" statement is that the lack thereof is part of the problem here. Users aren't protecting their attributes either out of ignorance or oversight. And to be fair, maybe the vulnerability isn't stressed enough in the documentation. (I haven't looked.) I'm not arguing against trying to mitigate potential disaster -- I'm all for it -- but I would also argue that if one doesn't truly understand why mass assignment is disabled by default, then he or she is liable to make their models insecure no matter what.

And for the users who are truly oblivious, here's what's going to happen anyway:

"I can't set user_id from this form. Let me just add user_id to the attr_accessible array, because that's what will make this action work the way I want it to."

That user doesn't understand what attr_accessible is for, why they'd want to whitelist attributes, why they need to whitelist attributes, and what can happen if they whitelist the wrong attributes. They might not even understand that they are whitelisting attributes -- they might think attr_accessible is some kind of riff on attr_accessor that adds getters and setters based on their schema.

At best, we're really just going to make it a little more difficult for them to screw themselves. Defaulting to a blacklist is an improvement to security, but no panacea. And I guess that's what I was getting at in my previous posts. It seems like some people are mindblown by all this, like allowing you to protect your attributes but not doing it by default is just nuts. We can go ahead and improve it, but there's still a dozen other gotchas awaiting the unprepared developer.

@mrrooijen

This comment has been minimized.

Show comment
Hide comment
@mrrooijen

mrrooijen Mar 6, 2012

@ELeo

Having all attributes blacklisted is arguably a safer default, as I said. It nonetheless makes assumptions about the application.

To be fair, this sorcery also made assumptions for all our Rails apps (for security reasons): 9415935

And for the users who are truly oblivious, here's what's going to happen anyway:

"I can't set user_id from this form. Let me just add user_id to the attr_accessible array, because that's what will make this action work the way I want it to."

If you're going to do this (setting attr_accessible) without knowing what it does, and you can't be arsed to look it up because you're too lazy, then you deserve to get "hacked". At this point, the average developer would look up what this does unless they already know, and understand what it's for.

At best, we're really just going to make it a little more difficult for them to screw themselves. Defaulting to a blacklist is an improvement to security, but no panacea. And I guess that's what I was getting at in my previous posts. It seems like some people are mindblown by all this, like allowing you to protect your attributes but not doing it by default is just nuts. We can go ahead and improve it, but there's still a dozen other gotchas awaiting the unprepared developer.

The first thing I pop in to the model when I create one is the attr_accessible method, just to ensure I don't forget, because I likely will since I'm busy implementing other things. Even if you know it exists, like GitHub, apparently even skilled programmers get screwed by Rails' defaults. Thankfully @homakov isn't an asshole, but assume he was, he could've done A LOT of damage with automated scripts to GitHub. Also, if this unprepared developer runs in to a lot of gotchas because of having to whitelist stuff, that's good, he or she will learn from them, best way to learn is trial and error. But at least he/she (unless he/she is a total noob, and cba to read docs to clarify what certain things actually do when in doubt and actually uses it wrong) won't be screwed the way GitHub was. Obviously GitHub is at fault here though, not Rails. When I heard the news about the mass-assignment issue + GitHub I thought people were trolling, before I actually read about it.

I don't really care whether attr_accessible blacklists everything by default or not. But from my point of view, by not having it as the default, it has the potential to cause a lot of damage to even experienced developers. Perhaps it's possible to have it on by default, with a flag in config/application.rb to disable it if it isn't necessary, or the other
way around, since everyone does stuff in the config/application.rb anyway and will see the option and be like: "oh yeah, flags it".

Might just go ahead and do this to be safe:

ActiveRecord::Base.send(:attr_accessible, nil)

Just my two cents.

mrrooijen commented Mar 6, 2012

@ELeo

Having all attributes blacklisted is arguably a safer default, as I said. It nonetheless makes assumptions about the application.

To be fair, this sorcery also made assumptions for all our Rails apps (for security reasons): 9415935

And for the users who are truly oblivious, here's what's going to happen anyway:

"I can't set user_id from this form. Let me just add user_id to the attr_accessible array, because that's what will make this action work the way I want it to."

If you're going to do this (setting attr_accessible) without knowing what it does, and you can't be arsed to look it up because you're too lazy, then you deserve to get "hacked". At this point, the average developer would look up what this does unless they already know, and understand what it's for.

At best, we're really just going to make it a little more difficult for them to screw themselves. Defaulting to a blacklist is an improvement to security, but no panacea. And I guess that's what I was getting at in my previous posts. It seems like some people are mindblown by all this, like allowing you to protect your attributes but not doing it by default is just nuts. We can go ahead and improve it, but there's still a dozen other gotchas awaiting the unprepared developer.

The first thing I pop in to the model when I create one is the attr_accessible method, just to ensure I don't forget, because I likely will since I'm busy implementing other things. Even if you know it exists, like GitHub, apparently even skilled programmers get screwed by Rails' defaults. Thankfully @homakov isn't an asshole, but assume he was, he could've done A LOT of damage with automated scripts to GitHub. Also, if this unprepared developer runs in to a lot of gotchas because of having to whitelist stuff, that's good, he or she will learn from them, best way to learn is trial and error. But at least he/she (unless he/she is a total noob, and cba to read docs to clarify what certain things actually do when in doubt and actually uses it wrong) won't be screwed the way GitHub was. Obviously GitHub is at fault here though, not Rails. When I heard the news about the mass-assignment issue + GitHub I thought people were trolling, before I actually read about it.

I don't really care whether attr_accessible blacklists everything by default or not. But from my point of view, by not having it as the default, it has the potential to cause a lot of damage to even experienced developers. Perhaps it's possible to have it on by default, with a flag in config/application.rb to disable it if it isn't necessary, or the other
way around, since everyone does stuff in the config/application.rb anyway and will see the option and be like: "oh yeah, flags it".

Might just go ahead and do this to be safe:

ActiveRecord::Base.send(:attr_accessible, nil)

Just my two cents.

@Alamoz

This comment has been minimized.

Show comment
Hide comment
@Alamoz

Alamoz Mar 6, 2012

@homakov I like what you say about controllers handling, managing and controlling business logic. Code runs faster in controllers than in models. The TDD fanatics like to put all business logic in the models because it is easier to test, but they apparently don't care about how fast it runs (the client can pay more for that later.) But I disagree about not filtering data in controllers. When you are working with complex data relationships, it may be necessary to place some of the filtering logic in the controller; but that logic is the app developer's responsibility, no special rails constructs are required. People need to realize the examples, even in the books, are simplistic. But sure, why not blacklist all mass assignment and require the dev to use attr_accessible, nothing wrong with that.

Alamoz commented Mar 6, 2012

@homakov I like what you say about controllers handling, managing and controlling business logic. Code runs faster in controllers than in models. The TDD fanatics like to put all business logic in the models because it is easier to test, but they apparently don't care about how fast it runs (the client can pay more for that later.) But I disagree about not filtering data in controllers. When you are working with complex data relationships, it may be necessary to place some of the filtering logic in the controller; but that logic is the app developer's responsibility, no special rails constructs are required. People need to realize the examples, even in the books, are simplistic. But sure, why not blacklist all mass assignment and require the dev to use attr_accessible, nothing wrong with that.

@jpoa

This comment has been minimized.

Show comment
Hide comment
@jpoa

jpoa Mar 6, 2012

@homakov Well done :)

It's github's admins fault, the man did all he could. It's time people start listening when things like these come by.

Again, well done, fully applaud.

jpoa commented Mar 6, 2012

@homakov Well done :)

It's github's admins fault, the man did all he could. It's time people start listening when things like these come by.

Again, well done, fully applaud.

@mazondo

This comment has been minimized.

Show comment
Hide comment
@mazondo

mazondo Mar 6, 2012

Agreed. Sorry, but all this nonsense about blacklisting by default being annoying is ridiculous. If attr_accessible is the "smart" way to go, then devs should be forced (at the very least encouraged) to use it.

On the off chance that they're creating something that requires absolutely no security (seriously?!?), they can deactivate the blacklist for themselves.

mazondo commented Mar 6, 2012

Agreed. Sorry, but all this nonsense about blacklisting by default being annoying is ridiculous. If attr_accessible is the "smart" way to go, then devs should be forced (at the very least encouraged) to use it.

On the off chance that they're creating something that requires absolutely no security (seriously?!?), they can deactivate the blacklist for themselves.

@wrzasa

This comment has been minimized.

Show comment
Hide comment
@wrzasa

wrzasa Mar 6, 2012

Rails is about reasonable conventions over configuration. Reasonable being the key word. In this case @homakov proved your conventions are not reasonable. And you ignored him. Lesson learned: don't trust rails conventions, they are not reasonable, so if what you just coded works, now sit with the documentation, read it all and check all possible options to find out what do the rails dev's screwed and fix it; if you fail to do it and trust their conventions, they will tell you it's your fault. It was foolish to turn @homakov away. Just don't goon wit it.

BTW: I use the attr_accessible and attr_protected in my apps from the very beginning. Anyway I support what @homakov proposed.

wrzasa commented Mar 6, 2012

Rails is about reasonable conventions over configuration. Reasonable being the key word. In this case @homakov proved your conventions are not reasonable. And you ignored him. Lesson learned: don't trust rails conventions, they are not reasonable, so if what you just coded works, now sit with the documentation, read it all and check all possible options to find out what do the rails dev's screwed and fix it; if you fail to do it and trust their conventions, they will tell you it's your fault. It was foolish to turn @homakov away. Just don't goon wit it.

BTW: I use the attr_accessible and attr_protected in my apps from the very beginning. Anyway I support what @homakov proposed.

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 6, 2012

@ELeo @meskyanichi was said all argument what I would like, so I would like to reply to just this:

You can't protect the user from everything.

This is absolute true. But, as a framework developer, I can protect my users from security problems caused by framework if it is possible. Developers are not a secretaries or nurses to I shouldn't assume they can't solve their problems but if I can help them to write better and more secure application then I must do it.

hron84 commented Mar 6, 2012

@ELeo @meskyanichi was said all argument what I would like, so I would like to reply to just this:

You can't protect the user from everything.

This is absolute true. But, as a framework developer, I can protect my users from security problems caused by framework if it is possible. Developers are not a secretaries or nurses to I shouldn't assume they can't solve their problems but if I can help them to write better and more secure application then I must do it.

@fny

This comment has been minimized.

Show comment
Hide comment
@fny

fny Mar 6, 2012

Contributor

Take a breath, and think naturally...

In life, people consciously and loudly choose to tote themselves in the nude. Even simple fashion is considered a statement:

attr_accesible birthday_suit # read: wildcard/regexp
attr_accesible keg, midriff, sixpack, love_handles
attr_protected sun_dont_shine, knockers, lingere, knicker_bockers
attr_protected bunny_suit # read: put the hazmat on the bunny

This is an issue of avoiding the dreaded nipslip or more poignantly protecting baby developers from rapists and pedophiles. Seriously, how much can you expect from a five-month-old?

Consider another analogy between escaped strings (which Rails quite aptly handles) and consumables. Cereal and arsenic shouldn't mix; medicines are proscribed by experts; and the LSD's for the adventurous. In the end, you choose, but you can't just allow anyone to shove anything into any orifice.

Sensible conventions reflect how we think, and thus make languages like Ruby and fameworks like Rails so wonderfully appealing and empowering. Flexibility shouldn't be compromised, of course: I'd be pissed if I had to fight to dress myself. But keep the infant in his diapers and sew the long-forgotten crotch holes in your buddy's pants (coughgithubcough.) After all, mistakes are only human. ;D

Contributor

fny commented Mar 6, 2012

Take a breath, and think naturally...

In life, people consciously and loudly choose to tote themselves in the nude. Even simple fashion is considered a statement:

attr_accesible birthday_suit # read: wildcard/regexp
attr_accesible keg, midriff, sixpack, love_handles
attr_protected sun_dont_shine, knockers, lingere, knicker_bockers
attr_protected bunny_suit # read: put the hazmat on the bunny

This is an issue of avoiding the dreaded nipslip or more poignantly protecting baby developers from rapists and pedophiles. Seriously, how much can you expect from a five-month-old?

Consider another analogy between escaped strings (which Rails quite aptly handles) and consumables. Cereal and arsenic shouldn't mix; medicines are proscribed by experts; and the LSD's for the adventurous. In the end, you choose, but you can't just allow anyone to shove anything into any orifice.

Sensible conventions reflect how we think, and thus make languages like Ruby and fameworks like Rails so wonderfully appealing and empowering. Flexibility shouldn't be compromised, of course: I'd be pissed if I had to fight to dress myself. But keep the infant in his diapers and sew the long-forgotten crotch holes in your buddy's pants (coughgithubcough.) After all, mistakes are only human. ;D

@azinazadi

This comment has been minimized.

Show comment
Hide comment
@azinazadi

azinazadi Mar 6, 2012

i think instead of fighting, rails people should find a nice solution for this problem. please

azinazadi commented Mar 6, 2012

i think instead of fighting, rails people should find a nice solution for this problem. please

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 6, 2012

Solution is in the repo, forcing security is enabled by default.

hron84 commented Mar 6, 2012

Solution is in the repo, forcing security is enabled by default.

@cmrichards

This comment has been minimized.

Show comment
Hide comment
@cmrichards

cmrichards Mar 6, 2012

Couldn't rails automatically use the input fields declared within the form_for block to determine what fields are allowed to be posted? This could be implemented by automatically inserting a special key at the end of the form, then the controller could only allow the declared parameters through to the actions.

cmrichards commented Mar 6, 2012

Couldn't rails automatically use the input fields declared within the form_for block to determine what fields are allowed to be posted? This could be implemented by automatically inserting a special key at the end of the form, then the controller could only allow the declared parameters through to the actions.

@cmrichards

This comment has been minimized.

Show comment
Hide comment
@cmrichards

cmrichards Mar 6, 2012

Would it be possible to encode the ids of every element in the form? Using sha1 or something like that. The form could also contain something that would assist in the decoding of the ids. The helper methods (form_for , text_field) would handle the encoding and the controller would automatically decode the params, so it would be transparent to the user.

cmrichards commented Mar 6, 2012

Would it be possible to encode the ids of every element in the form? Using sha1 or something like that. The form could also contain something that would assist in the decoding of the ids. The helper methods (form_for , text_field) would handle the encoding and the controller would automatically decode the params, so it would be transparent to the user.

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 6, 2012

@evilgeenius No, it is not possible, because the name attribute what is really matters. And it is needed for compute params array. And from SHA1 you cannot decode anything, because you do not needed to name your form elements as same as attribute names - it is just a help for you. But, the form-decoding logic is cannot guess what do you want to get in your form, and if the choosen encoding is decodeable, then hacker can decode it relative easily - so it is not a protection, but security through obscurity - not needed, unusable, and does not matter.

And form_for is just generates a HTML form. It is not related to handling incoming parameters. And,you cannot restrict incoming parameters on the level of framework, because it is an application-dependent thing.

hron84 commented Mar 6, 2012

@evilgeenius No, it is not possible, because the name attribute what is really matters. And it is needed for compute params array. And from SHA1 you cannot decode anything, because you do not needed to name your form elements as same as attribute names - it is just a help for you. But, the form-decoding logic is cannot guess what do you want to get in your form, and if the choosen encoding is decodeable, then hacker can decode it relative easily - so it is not a protection, but security through obscurity - not needed, unusable, and does not matter.

And form_for is just generates a HTML form. It is not related to handling incoming parameters. And,you cannot restrict incoming parameters on the level of framework, because it is an application-dependent thing.

@wrzasa

This comment has been minimized.

Show comment
Hide comment
@wrzasa

wrzasa Mar 6, 2012

On 06.03.2012 20:17, Gabor Garami wrote:

@evilgeenius Decoding? From SHA1? No, it is not possible. But what do you mean?

I think he meant attaching a kind of control sum to each form, to allow
controllers to automatically verify if there were any additional fields
added to the form by an attacker.

wrzasa
<

wrzasa commented Mar 6, 2012

On 06.03.2012 20:17, Gabor Garami wrote:

@evilgeenius Decoding? From SHA1? No, it is not possible. But what do you mean?

I think he meant attaching a kind of control sum to each form, to allow
controllers to automatically verify if there were any additional fields
added to the form by an attacker.

wrzasa
<

@norv

This comment has been minimized.

Show comment
Hide comment
@norv

norv Mar 7, 2012

Can someone please point out to me a reasonable use case, for a web application, when you don't need to make sure your POSTed data is exactly what you're expecting?

I seem to see people think there are cases where not being forced to be explicit about what you allow, would be... needed, apparently. I'd appreciate a case.

norv commented Mar 7, 2012

Can someone please point out to me a reasonable use case, for a web application, when you don't need to make sure your POSTed data is exactly what you're expecting?

I seem to see people think there are cases where not being forced to be explicit about what you allow, would be... needed, apparently. I'd appreciate a case.

@wrzasa

This comment has been minimized.

Show comment
Hide comment
@wrzasa

wrzasa Mar 7, 2012

On 07.03.2012 14:00, Norv wrote:

Can someone please point out to me a reasonable use case, for a web
application, when you don't need to make sure your POSTed data is
exactly what you're expecting?

I seem to see people think there are cases where not being forced to be
explicit about what you allow, would be... needed, apparently. I'd
appreciate a case.

There are cases when you don't care, because your model contains only the
fileds that the user is allowed to edit, so an attacker would gain nothing.
This is the only use case at least loosely connected with what you asked. I
can't see any other.

Your question is even more important in case of RoR where my use case is
never true, becasue every model contains at least updated_at and created_at
and in most cases no user should be allowed edited them.

wrzasa commented Mar 7, 2012

On 07.03.2012 14:00, Norv wrote:

Can someone please point out to me a reasonable use case, for a web
application, when you don't need to make sure your POSTed data is
exactly what you're expecting?

I seem to see people think there are cases where not being forced to be
explicit about what you allow, would be... needed, apparently. I'd
appreciate a case.

There are cases when you don't care, because your model contains only the
fileds that the user is allowed to edit, so an attacker would gain nothing.
This is the only use case at least loosely connected with what you asked. I
can't see any other.

Your question is even more important in case of RoR where my use case is
never true, becasue every model contains at least updated_at and created_at
and in most cases no user should be allowed edited them.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Mar 7, 2012

@norv In the real world, there aren't a lot. One exception is where the data is coming from a "trusted" user, e.g. an admin. Sure, maybe there's fields you want to secure even from an admin, or maybe not, or maybe you just figure it doesn't matter if they want to hack their own app, if they want to go to those lengths.

However, not every model deals with POSTed data, and some do but only indirectly.

For example, a project I work on imports XML data from a "trusted" source, so in these kinds of models, there's no need for security. There are numerous models in the project like this. I'd essentially have to attr_accessible every last column, if the default were for all attributes to be blacklisted by default. This is somewhat arduous, and is somewhat of a maintainability headache, because if the schema changes later on, I have to add those new fields to the attr_accessible list.

If we're going to go with a blacklisted-by-default approach, is there some way for me to auto-whitelist every attribute without having to be so explicit as to type out each one?

ghost commented Mar 7, 2012

@norv In the real world, there aren't a lot. One exception is where the data is coming from a "trusted" user, e.g. an admin. Sure, maybe there's fields you want to secure even from an admin, or maybe not, or maybe you just figure it doesn't matter if they want to hack their own app, if they want to go to those lengths.

However, not every model deals with POSTed data, and some do but only indirectly.

For example, a project I work on imports XML data from a "trusted" source, so in these kinds of models, there's no need for security. There are numerous models in the project like this. I'd essentially have to attr_accessible every last column, if the default were for all attributes to be blacklisted by default. This is somewhat arduous, and is somewhat of a maintainability headache, because if the schema changes later on, I have to add those new fields to the attr_accessible list.

If we're going to go with a blacklisted-by-default approach, is there some way for me to auto-whitelist every attribute without having to be so explicit as to type out each one?

@levhita

This comment has been minimized.

Show comment
Hide comment
@levhita

levhita Mar 7, 2012

Probably a simple configuration should be enough blacklisted-by-default , a config to change it to whitelisted-by-default and the option to change it directly in the model at run time.

I don't see the problem really and rails has just maked a fool of itself...

PD: If you advertise you framework as "even an idiot can make a page in 30 minutes" you will end up with a lot of idiots writing pages in 30 minutes...

levhita commented Mar 7, 2012

Probably a simple configuration should be enough blacklisted-by-default , a config to change it to whitelisted-by-default and the option to change it directly in the model at run time.

I don't see the problem really and rails has just maked a fool of itself...

PD: If you advertise you framework as "even an idiot can make a page in 30 minutes" you will end up with a lot of idiots writing pages in 30 minutes...

@csuhta

This comment has been minimized.

Show comment
Hide comment

csuhta commented Mar 7, 2012

@RangelReale

This comment has been minimized.

Show comment
Hide comment
@RangelReale

RangelReale Mar 7, 2012

To me it seems obvious from the start that mass assignment should be disabled by default.

Otherwise, you add a field on a table, and you have to remember to block it on the model? If the field would be user-assignable, then of course a form would have to be modified to add an input, and at THIS time, you would modify the model, because it is related to the same change.

Yii framework in PHP which is very similar to Rails, blocks alls fields by default since the beginning.

If this is common practice in the Rails community, I would never trust a Rails application. This is as bad as SQL injection.

RangelReale commented Mar 7, 2012

To me it seems obvious from the start that mass assignment should be disabled by default.

Otherwise, you add a field on a table, and you have to remember to block it on the model? If the field would be user-assignable, then of course a form would have to be modified to add an input, and at THIS time, you would modify the model, because it is related to the same change.

Yii framework in PHP which is very similar to Rails, blocks alls fields by default since the beginning.

If this is common practice in the Rails community, I would never trust a Rails application. This is as bad as SQL injection.

@Alamoz

This comment has been minimized.

Show comment
Hide comment
@Alamoz

Alamoz Mar 7, 2012

Just received an email from GitHub, perhaps related to this issue:

"A security vulnerability was recently discovered that made it possible for an attacker to add new SSH keys to arbitrary GitHub user accounts. This would have provided an attacker with clone/pull access to repositories with read permissions, and clone/pull/push access to repositories with write permissions. As of 5:53 PM UTC on Sunday, March 4th the vulnerability no longer exists."

Alamoz commented Mar 7, 2012

Just received an email from GitHub, perhaps related to this issue:

"A security vulnerability was recently discovered that made it possible for an attacker to add new SSH keys to arbitrary GitHub user accounts. This would have provided an attacker with clone/pull access to repositories with read permissions, and clone/pull/push access to repositories with write permissions. As of 5:53 PM UTC on Sunday, March 4th the vulnerability no longer exists."

@norv

This comment has been minimized.

Show comment
Hide comment
@norv

norv Mar 8, 2012

Thank you!

@ELeo I was going to point out the commit above - cjcsuhta already mentioned it.
Reversing the switch is possible, for one's particular application.

The possibility of different sources for the data getting to the model, than http form input, and needing different treatment for them, tells me again that: authorization, filtering of the incoming data, and even validation needed for the data, are not really model issues. They may apply on the model, or be aware of it, but they cannot and should not be handled all at model level, otherwise you can't really have flexibility nor security as needed.
The handlers of those actions (i.e. controllers, forms, actions classes) should be responsible, directly or indirectly.

On the other hand, since in the case of web form data, there is an always-present need for request filtering, authorization, and validation, I find it more than reasonable to address these concerns at the level of a web framework.
If it's at the expense of convenience, then at the expense of convenience.
Security >> convenience.

At most, validation, from this list, may be disputable as to where it belongs, it may be the choice of a particular framework to handle it more tied to the model itself. I just don't see how could the rest be model matters, and in the same time have a both flexible and secure framework for development.
(Nevertheless, the commit pointed out above is IMO a step in the right direction, at least it makes sure the defaults will be saner).

Side note: I'd say admin is not really an exception in the sense of my question, since checking if the current user is an admin means an authorization check.

norv commented Mar 8, 2012

Thank you!

@ELeo I was going to point out the commit above - cjcsuhta already mentioned it.
Reversing the switch is possible, for one's particular application.

The possibility of different sources for the data getting to the model, than http form input, and needing different treatment for them, tells me again that: authorization, filtering of the incoming data, and even validation needed for the data, are not really model issues. They may apply on the model, or be aware of it, but they cannot and should not be handled all at model level, otherwise you can't really have flexibility nor security as needed.
The handlers of those actions (i.e. controllers, forms, actions classes) should be responsible, directly or indirectly.

On the other hand, since in the case of web form data, there is an always-present need for request filtering, authorization, and validation, I find it more than reasonable to address these concerns at the level of a web framework.
If it's at the expense of convenience, then at the expense of convenience.
Security >> convenience.

At most, validation, from this list, may be disputable as to where it belongs, it may be the choice of a particular framework to handle it more tied to the model itself. I just don't see how could the rest be model matters, and in the same time have a both flexible and secure framework for development.
(Nevertheless, the commit pointed out above is IMO a step in the right direction, at least it makes sure the defaults will be saner).

Side note: I'd say admin is not really an exception in the sense of my question, since checking if the current user is an admin means an authorization check.

@dburry

This comment has been minimized.

Show comment
Hide comment
@dburry

dburry Mar 15, 2012

We developers using Rails should not have to write Merb or 0day the repo in order to get core Rails devs to stop saying "The emperor DOES SO have clothes!" Core devs, please change your attitude. We want newly-generated rails apps to have a setting in the application.rb that by-default turns off mass assignment, unless we reverse that setting in the application.rb or on a model by model basis. This way it's backwards compatible with existing apps too. Most of us want this. Stop making us resort to such tactics for anyone on the core team to listen.

dburry commented Mar 15, 2012

We developers using Rails should not have to write Merb or 0day the repo in order to get core Rails devs to stop saying "The emperor DOES SO have clothes!" Core devs, please change your attitude. We want newly-generated rails apps to have a setting in the application.rb that by-default turns off mass assignment, unless we reverse that setting in the application.rb or on a model by model basis. This way it's backwards compatible with existing apps too. Most of us want this. Stop making us resort to such tactics for anyone on the core team to listen.

@hron84

This comment has been minimized.

Show comment
Hide comment
@hron84

hron84 Mar 16, 2012

@dburry you knocking on the open door. Please read back this issue, the future Rails versions will come with enabled enforcement.

hron84 commented Mar 16, 2012

@dburry you knocking on the open door. Please read back this issue, the future Rails versions will come with enabled enforcement.

@dburry

This comment has been minimized.

Show comment
Hide comment
@dburry

dburry Mar 17, 2012

@hron84 indeed, for this issue... but will our attitudes change enough from this experience so that such tactics won't be necessary with other issues? I see the attitudes as the root cause that made this issue go so long ignored. And I realize this is more a social thing than a technical thing, so maybe this isn't the right forum for me to keep talking about it, sorry :P

dburry commented Mar 17, 2012

@hron84 indeed, for this issue... but will our attitudes change enough from this experience so that such tactics won't be necessary with other issues? I see the attitudes as the root cause that made this issue go so long ignored. And I realize this is more a social thing than a technical thing, so maybe this isn't the right forum for me to keep talking about it, sorry :P

@sampablokuper

This comment has been minimized.

Show comment
Hide comment
@sampablokuper

sampablokuper Jun 9, 2012

Isn't the question of whether mass assignment is enabled or disabled by default a bit of a red herring? I've just posted a question to this effect at SO, if anyone's interested.

sampablokuper commented Jun 9, 2012

Isn't the question of whether mass assignment is enabled or disabled by default a bit of a red herring? I've just posted a question to this effect at SO, if anyone's interested.

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Jun 9, 2012

Contributor

@sampablokuper Answer is No. User is able to update HIS public key record AND he updates it with new user_id. code:

pk=current_user.public_keys.find(params[:id])
pk.update_attributes! params[:public_key]
Contributor

homakov commented Jun 9, 2012

@sampablokuper Answer is No. User is able to update HIS public key record AND he updates it with new user_id. code:

pk=current_user.public_keys.find(params[:id])
pk.update_attributes! params[:public_key]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment