Form Data Injection - How to protect against?

I might be missing something here, but it seems as if the conventions used when building forms in Rails apps leave a lot of open holes for people to mess things up. For instance, let's say I have a multi-user community app with a simple user profile page where users can edit their profile. Not uncommon.

Now, on that page they can change things like their name, web site, IM info, etc. But with what seems to be standard practice of updating that info, as so...

def update   @user = User.find(params[:id])   if @user.update_attributes(params[:user])     etc., etc.

...it seems like you are open for major problems. Let's say you have a role field on your model. It seems trivial to have someone inject their own form data into the headers to add the equivalent of...

<input id="user_role" name="user[role]" type="hidden" value="Administrator" />

...and have that be passed along with the .update_attributes method. Am I wrong?

Is there some common practice of protecting against this that I am just missing? And if this isn't common practice, it should be, shouldn't it? There is the obvious blunt route of being super-careful and checking every field of the model, regardless of whether it's on the form or not, but I don't see that being practiced, so I thought maybe I'm missing something.

You missed attr_accessible and it's partner attr_protected in the models. :slight_smile:

You are correct, and you are missing attr_protected and attr_accessible.

You are very right. I did. I just finished reading up about them. And following other discussions on this topic. Like

I pointed the people in #rubyonrails on freenode to this post and got a quick answer from stympy about checking out attr_protected and attr_accessible. Knowing that was the answer, I was able to find quite a lot of data. I simply had the wrong search terms for getting my question answered. :slight_smile:

Here's what you need...

http://manuals.rubyonrails.com/read/chapter/47

Dylan Bennett wrote:

Another thing you need to keep in mind is about 'access rights' to the record, not just to fields within the record. I, as user_id = 10 can go to /users/10;edit, but I cannot go to /users/1;edit.

In my user controller I have this:   # I already declare basic authentication in my application.rb   before_filter :verify_user, :except => [ :check_field, :create, :new, :retrieve_password ]

protected   def verify_user     return true if params[:id].nil? || params[:id].to_i == session[:user]     flash[:error] = "You are not allowed to see another users Settings screen."     redirect_to_default     false   end

and that works like a charm Adam