In my app, a user logs in [via the login generator] and has access to details of his account, and transactions attached to his account. This is achieved in the standard rail manner by passing the account id or transaction id between the controller and the view. But what is to stop someone hacking the URL or view html to access another account id or transaction id ? eg /account/show/46 becomes /account/show/53 or /transaction/show/44 becomes /transaction/show/77 Well, I can change every find_by_* to include the account id from the session [is this safe, ie, what about cookie hacking?] What other techniques are people using to cope with ''id'' hacking? Thanks Neville _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
On Sat, 5 Mar 2005 23:09:27 +1100, Neville Burnell <Neville.Burnell-uEDVyssJ3mUpAS55Wn97og@public.gmane.org> wrote:> But what is to stop someone hacking the URL or view html to access another > account id or transaction id ? > eg /account/show/46 becomes /account/show/53 or /transaction/show/44 becomes > /transaction/show/77Well, from the sounds of your question, nothing is to stop somebody from doing this. Have you tried it to make sure it actually works? What I would do in your situation is to modify the show action on those controllers so that they don''t take the id from the URL but from the session. That way somebody accessing "/account/show" or "/transaction/show" can only see their own details, and nobody else''s.> Well, I can change every find_by_* to include the account id from the > session [is this safe, ie, what about cookie hacking?]No need to change all the find_by_* methods... just change something like this: def show @account = Account.find(@params[''id'']) end to something like this (I''m guessing here, don''t hurt me if this doesn''t work): def show @account = Account.find(@session[''user''][''id'']) end Of course replace "account" with the actual variable and class names that you use in your rails app. -- One Guy With A Camera http://rbpark.ath.cx
Rob Park wrote:>>Well, I can change every find_by_* to include the account id from the >>session [is this safe, ie, what about cookie hacking?] >> >> > >No need to change all the find_by_* methods... just change something like this: > > def show > @account = Account.find(@params[''id'']) > end > >to something like this (I''m guessing here, don''t hurt me if this doesn''t work): > > def show > @account = Account.find(@session[''user''][''id'']) > end > >Of course replace "account" with the actual variable and class names >that you use in your rails app. > > >This does not work if you have objects, which are not indexed with the id of the user as primary key, which seems to be the case in Neville''s example about his "Transaction" class (and is quite common). In this case you have to either create your own finder methods, which pass the current user id taken from the session into the query (if the user id is a foreign key of that specific object), or you have to check the ownership of the object you are about to show/modify, and redirect the user somewhere else if he is not the owner. The second case increases the orthogonality of your models, as you create an implicit dependency to the rails framework with the modification of the finder methods (session has to be there, session has to have a user object). OTOH you have to check the ownership in the controller for every action if you prefer the second case, either by adding a rather "static" before/after_filter, or by manually doing it for each action. Which case you choose depends on your scenario, and your data model. Because you mentioned "cookie-hacking": it is very easy to take over a rails-session if you know the value of the session-cookie. It is not possible to prevent that easily, you can just make it harder by encrypting the whole session (right from the beginning when the user enters the site, and the cookie is created) by using https. Kind regards, Dennis Oelkers
this might help you too http://manuals.rubyonrails.com/read/chapter/47 Rob Park wrote:> On Sat, 5 Mar 2005 23:09:27 +1100, Neville Burnell > <Neville.Burnell-uEDVyssJ3mUpAS55Wn97og@public.gmane.org> wrote: > >>But what is to stop someone hacking the URL or view html to access another >>account id or transaction id ? >>eg /account/show/46 becomes /account/show/53 or /transaction/show/44 becomes >>/transaction/show/77 > > > Well, from the sounds of your question, nothing is to stop somebody > from doing this. Have you tried it to make sure it actually works? > > What I would do in your situation is to modify the show action on > those controllers so that they don''t take the id from the URL but from > the session. That way somebody accessing "/account/show" or > "/transaction/show" can only see their own details, and nobody else''s. > > >>Well, I can change every find_by_* to include the account id from the >>session [is this safe, ie, what about cookie hacking?] > > > No need to change all the find_by_* methods... just change something like this: > > def show > @account = Account.find(@params[''id'']) > end > > to something like this (I''m guessing here, don''t hurt me if this doesn''t work): > > def show > @account = Account.find(@session[''user''][''id'']) > end > > Of course replace "account" with the actual variable and class names > that you use in your rails app. >
Thanks for the link ... This doc certainly helps with other issues, but not ''id hacking''. -----Original Message----- From: rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Francisco Hernandez Sent: Sunday, 6 March 2005 6:23 AM To: Rob Park; rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: Re: [Rails] Best practice to manage ''id'' hacking? this might help you too http://manuals.rubyonrails.com/read/chapter/47 Rob Park wrote:> On Sat, 5 Mar 2005 23:09:27 +1100, Neville Burnell > <Neville.Burnell-uEDVyssJ3mUpAS55Wn97og@public.gmane.org> wrote: > >>But what is to stop someone hacking the URL or view html to access >>another account id or transaction id ? >>eg /account/show/46 becomes /account/show/53 or /transaction/show/44 >>becomes >>/transaction/show/77 > > > Well, from the sounds of your question, nothing is to stop somebody > from doing this. Have you tried it to make sure it actually works? > > What I would do in your situation is to modify the show action on > those controllers so that they don''t take the id from the URL but from> the session. That way somebody accessing "/account/show" or > "/transaction/show" can only see their own details, and nobody else''s. > > >>Well, I can change every find_by_* to include the account id from the >>session [is this safe, ie, what about cookie hacking?] > > > No need to change all the find_by_* methods... just change somethinglike this:> > def show > @account = Account.find(@params[''id'']) > end > > to something like this (I''m guessing here, don''t hurt me if thisdoesn''t work):> > def show > @account = Account.find(@session[''user''][''id'']) > end > > Of course replace "account" with the actual variable and class names > that you use in your rails app. >_______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Maybe I''m missing something obvious here but in my app I have users log in with a username and password but their ID is never displayed. each Person is tied to a variety of top level objects that they have permission to see via a join table. They log in, I pull up a page and display what they''re allowed to see via the contents of that join table. Then it''s just a matter of checking the association to the things in your pages in case, on other pages where they can do ID hacking they don''t see anything that isn''t tied to them. -Kate On Sat, 05 Mar 2005 19:31:48 +0100, Dennis Oelkers <dennis-TFyySJyCJcUbwZ3undymew@public.gmane.org> wrote:> Rob Park wrote: > > >>Well, I can change every find_by_* to include the account id from the > >>session [is this safe, ie, what about cookie hacking?] > >> > >> > > > >No need to change all the find_by_* methods... just change something like this: > > > > def show > > @account = Account.find(@params[''id'']) > > end > > > >to something like this (I''m guessing here, don''t hurt me if this doesn''t work): > > > > def show > > @account = Account.find(@session[''user''][''id'']) > > end > > > >Of course replace "account" with the actual variable and class names > >that you use in your rails app. > > > > > > > This does not work if you have objects, which are not indexed with the > id of the user as primary key, which seems > to be the case in Neville''s example about his "Transaction" class (and > is quite common). > > In this case you have to either create your own finder methods, which > pass the current user id taken from the session > into the query (if the user id is a foreign key of that specific > object), or you have to check the ownership of the object > you are about to show/modify, and redirect the user somewhere else if he > is not the owner. > The second case increases the orthogonality of your models, as you > create an implicit dependency to the rails framework > with the modification of the finder methods (session has to be there, > session has to have a user object). > OTOH you have to check the ownership in the controller for every action > if you prefer the second case, either by adding > a rather "static" before/after_filter, or by manually doing it for each > action. > > Which case you choose depends on your scenario, and your data model. > > Because you mentioned "cookie-hacking": it is very easy to take over a > rails-session if you know the value of the > session-cookie. It is not possible to prevent that easily, you can just > make it harder by encrypting the whole session > (right from the beginning when the user enters the site, and the cookie > is created) by using https. > > Kind regards, > Dennis Oelkers > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- -Kate (masukomi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org)
Hi Kate, Can your user do the following: 1) login & get hidden user id [secure] 2) select list of objects via join table [secure] 3) select an object from the list to view by id? If so, then changing the URL for step 3 from a valid id of say 44 derived from the join to another valid id of 77 belonging to another user might constitute id hacking [at a lower level] in your app. In my app, you can go from account->order list->order detail->line list->line detail Even though the original id''s are generated by the app, as soon as the user has an id for say line id 44 at the lowest level, they have an opportunity to create a url to view a different id that wasn''t generated ''legally'' by the app. -----Original Message----- From: rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of kate rhodes Sent: Sunday, 6 March 2005 2:03 PM To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: Re: [Rails] Best practice to manage ''id'' hacking? Maybe I''m missing something obvious here but in my app I have users log in with a username and password but their ID is never displayed. each Person is tied to a variety of top level objects that they have permission to see via a join table. They log in, I pull up a page and display what they''re allowed to see via the contents of that join table. Then it''s just a matter of checking the association to the things in your pages in case, on other pages where they can do ID hacking they don''t see anything that isn''t tied to them. -Kate On Sat, 05 Mar 2005 19:31:48 +0100, Dennis Oelkers <dennis-TFyySJyCJcUbwZ3undymew@public.gmane.org> wrote:> Rob Park wrote: > > >>Well, I can change every find_by_* to include the account id from > >>the session [is this safe, ie, what about cookie hacking?] > >> > >> > > > >No need to change all the find_by_* methods... just change somethinglike this:> > > > def show > > @account = Account.find(@params[''id'']) end > > > >to something like this (I''m guessing here, don''t hurt me if thisdoesn''t work):> > > > def show > > @account = Account.find(@session[''user''][''id'']) > > end > > > >Of course replace "account" with the actual variable and class names > >that you use in your rails app. > > > > > > > This does not work if you have objects, which are not indexed with the> id of the user as primary key, which seems to be the case in Neville''s> example about his "Transaction" class (and is quite common). > > In this case you have to either create your own finder methods, which > pass the current user id taken from the session into the query (if the> user id is a foreign key of that specific object), or you have to > check the ownership of the object you are about to show/modify, and > redirect the user somewhere else if he is not the owner. > The second case increases the orthogonality of your models, as you > create an implicit dependency to the rails framework with the > modification of the finder methods (session has to be there, session > has to have a user object). > OTOH you have to check the ownership in the controller for every > action if you prefer the second case, either by adding a rather > "static" before/after_filter, or by manually doing it for each action. > > Which case you choose depends on your scenario, and your data model. > > Because you mentioned "cookie-hacking": it is very easy to take over > a rails-session if you know the value of the session-cookie. It is not> possible to prevent that easily, you can just make it harder by > encrypting the whole session (right from the beginning when the user > enters the site, and the cookie is created) by using https. > > Kind regards, > Dennis Oelkers > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- -Kate (masukomi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org) _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Neville Burnell wrote:> Even though the original id''s are generated by the app, as soon as the > user has an id for say line id 44 at the lowest level, they have an > opportunity to create a url to view a different id that wasn''t generated > ''legally'' by the app.Don''t show lines to users who don''t own them. You may find the line by following associations from the user: user.orders.find(@params[''order_id'']).lines.find(@params[''line_id'']) Your controller don''t have to be pure-CRUD; that''s better suited to an admin interface. jeremy
On Sat, 05 Mar 2005 22:08:24 -0800, Jeremy Kemper <jeremy-w7CzD/W5Ocjk1uMJSBkQmQ@public.gmane.org> wrote:> Neville Burnell wrote: > > Even though the original id''s are generated by the app, as soon as the > > user has an id for say line id 44 at the lowest level, they have an > > opportunity to create a url to view a different id that wasn''t generated > > ''legally'' by the app. > > Don''t show lines to users who don''t own them. You may find the line by > following associations from the user: > user.orders.find(@params[''order_id'']).lines.find(@params[''line_id''])Exactly, your application should have all the associations represented in its object model. You now have to use them to restrict the queries. It''ll be slower, but it will actually be secure, which is much more important.> Your controller don''t have to be pure-CRUD; that''s better suited to an > admin interface. > > jeremy > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Cheers Koz
Thanks, that will work great. I _get_ it [finally]!> Don''t show lines to users who don''t own them. You may find the line > by following associations from the user: > user.orders.find(@params[''order_id'']).lines.find(@params[''line_id''])Exactly, your application should have all the associations represented in its object model. You now have to use them to restrict the queries. It''ll be slower, but it will actually be secure, which is much more important.