encrypt id in url controller/action/id

i am developing a community which has user profiles ... those are now accessible through an url like e.g.

/user/profile/10

the 10 is the id of the user within the database. now i dont really like the plain ID within the url because it is very simple to iterate through the users ..

does someone has a nice solution for encrypting and decrypting the id? some simple encryption would be fine

Michal Gabrukiewicz said the following on 06/01/08 04:17 PM:

i am developing a community which has user profiles ... those are now accessible through an url like e.g.

/user/profile/10

the 10 is the id of the user within the database. now i dont really like the plain ID within the url because it is very simple to iterate through the users ..

Yes, this is an intrinsic security flaw that appears in much of Rails:

  http://example.com/web/84/topic/12379

A simple loop can find out all the projects, all the topics.

This kind of scanning is a common 'pre-attack' scan used by malicious hackers.

Anton Aylward wrote:

Michal Gabrukiewicz said the following on 06/01/08 04:17 PM:

i am developing a community which has user profiles ... those are now accessible through an url like e.g.

/user/profile/10

the 10 is the id of the user within the database. now i dont really like the plain ID within the url because it is very simple to iterate through the users ..

Yes, this is an intrinsic security flaw that appears in much of Rails:

  http://example.com/web/84/topic/12379

A simple loop can find out all the projects, all the topics.

This kind of scanning is a common 'pre-attack' scan used by malicious hackers.

and do u have a solution?

Michal Gabrukiewicz said the following on 06/01/08 05:12 PM:

Anton Aylward wrote:

Michal Gabrukiewicz said the following on 06/01/08 04:17 PM:

i am developing a community which has user profiles ... those are now accessible through an url like e.g.

/user/profile/10

the 10 is the id of the user within the database. now i dont really like the plain ID within the url because it is very simple to iterate through the users ..

Yes, this is an intrinsic security flaw that appears in much of Rails:

  http://example.com/web/84/topic/12379

A simple loop can find out all the projects, all the topics.

This kind of scanning is a common 'pre-attack' scan used by malicious hackers.

and do u have a solution?

There are many. Google for security, but you're on the right idea when you talk about 'encrypt' the ID. Of course the internal 'find_by_id' and the external form in the URL can be different.

How strong do you want it to be? How meaningful do you want it to be?

If users sign up as "Firstname, Lastname" you could make that the ID - CamelWord it to FirstnameLastname and get

        /user/profile/FirstnameLastname

This is 'meaningful'. Its not obscure, but at least its immune to easy "Brute Force"attacks of the form

   [1 ... 100000000].each { |i| attack.send("/usr/profile/" + i.to_s) }

To be really paranoid, you could take

       sha1hash(firstname.to_s + lastname.to_s)

Yes, it would be possible to generate a big list of names, but think about this:

firstname.length and lastname.length can vary from 2 to 20 (or whatever) characters. A generator for all that would take a long time to run. An attack like this would show up in your log files and IDS quite clearly.

Log files monitoring? IDS? They too are part of security. You can't just rely on programming. Security is about overlapping checks and controls. But even so, all you're doing is uppng the ante, and there may be other areas of attack. Residual risk - Wikipedia

  1. If you don’t want it to be seen, it should have been in a password protected part of your site. Never trust user input, whether it’s in forms or in urls.

  2. If you want to avoid record scraping for data within the pages, use different techniques like clientside decrypting of encrypted elements or use rmagick to render the data as an image instead of a string.

  3. If you want to avoid record scraping of entire pages over your complete database or brute force attacks, use log file analyzers that reconfigure your firewall to ban those ips when certain conditions are met. fail2ban is such a solution.

  4. If you want to avoid hotlinking to files, use Apache/other webserver techniques to avoid it.

  5. If you need to make temporary file downloads with a hash in the url, use a simple named route instead of shoving it in a RESTful route.

Believe me, this kind of scraping is the thing you need to worry about the least.

Best regards

Peter De Berdt

thanks for the answers guys .. but i am looking for the best solution to encrypt and decrypt the id of my user ..

anton i thought about your solution with first and lastname but i could have duplicate names and then its not that straightforward anymore ...

i just want to crypt the id so it does not look obvious that you can just grab all of them with bruteforce

Peter De Berdt said the following on 06/01/08 06:08 PM:

This kind of scanning is a common 'pre-attack' scan used by malicious

hackers.

1. If you don't want it to be seen, it should have been in a password protected part of your site. Never trust user input, whether it's in forms or in urls.

Absolutely.

The       Post.find( .... params[:post] ...) is high risk. Always sanitise and filter your inputs. The example given in AWDWR about cross-site-scripting is just the beginning.

2. If you want to avoid record scraping for data within the pages, use different techniques like clientside decrypting of encrypted elements or use rmagick to render the data as an image instead of a string.

Just as a generation of spammers did to try and get around SpamAssassin. (Only it didn't work.)

3. If you want to avoid record scraping of entire pages over your complete database or brute force attacks, use log file analyzers that reconfigure your firewall to ban those ips when certain conditions are met. fail2ban is such a solution.

Log file analysis and IDS/IPS are an essential part of a security strategy.

4. If you want to avoid hotlinking to files, use Apache/other webserver techniques to avoid it.

Again, well documented.

5. If you need to make temporary file downloads with a hash in the url, use a simple named route instead of shoving it in a RESTful route.

LOL! And yes, lots of sites use temporary URL strings with limited lifetimes. Its no different from fixed lifetime values in the cookies.

Believe me, this kind of scraping is the thing you need to worry about the least.

... until you get bitten.

The cost of retrofitting security after an incident is always going to be greater than the cost of addressing the risks when designing the system. You don't always have to load up the complete suite of security tools from the start, but do think about it.

Sometimes small architectural changes that don't really affect the code development can make a big positive or negative impact on security.

Sometimes it IS coding style. For example, I list the real actions in controllers with 'public ....' and use 'hide_action'. But then I'm a bit paranoid. (Actually I'm paid to be paranoid.)

There is a great deal of information on secure programming style and considerations. Some is language specific and some is perfectly general. Some that seems specific because of the examples is actually quite general. (injection attacks, XSS, print format string hijacking ...)

http://www.securecoding.org/companion/links.php

Consider also that the term 'security' means more than keeping hackers and attacks out. You may have a requirement for availability and for protecting PII or maintaining integrity of records. To say nothing of 'resilience and robustness', for example ensuring availability to legitimate users in the faces of DoS attack.

See also http://rubythis.blogspot.com/2006/11/rails-security-checklist.html http://nob.cs.ucdavis.edu/bishop/papers/2006-cisse-2/clinic.pdf http://press.oreilly.com/pub/pr/1388     Rubyists can always learn from Perl - one way or another :slight_smile:

Michal Gabrukiewicz said the following on 06/01/08 07:27 PM:

thanks for the answers guys .. but i am looking for the best solution to encrypt and decrypt the id of my user ..

anton i thought about your solution with first and lastname but i could have duplicate names and then its not that straightforward anymore ...

I use this on my Wiki. Dealing with 'duplicates' is straight forward if you think about it. There are many possible solutions.

What I do is prompt for first and last name and then use javascript to join them and check to see if that already exists. If it does I add a digit and try again. The result is offered as a suggestion, the user can change it and "submit", but that might still be a duplicate, so he gees told and we go round again.

Luckily I have a pretty unique name, but at some sites I'm "anton1" or even "anton7"

But the important thing is defending against Brute Force and predictable sequence attacks. As I said, the basic id# approach of AWDWR is a CFM.

Perhaps you could add salt to this, such as their user id? Encrypt their first name, last name AND id to ensure a different result from everyone else?

On Jan 7, 2008 12:18 PM, Anton J Aylward < aja@si.on.ca> wrote:

cant i just take the id and encrypt it using a key (chosen by me) and then decrypt it before i use it within the application .. this is what i would like to achive ... i dont want to hash the values because then i cannot really use it within my queries..

Perhaps change the URL to something like 10-michal-gabrukiewicz, or even just michal-gabrukiewicz. When a user changes their first and last names, save this as another field in the table as that (michal-gabukiewicz) and then do a find by that field.

Ryan Bigg wrote:

Perhaps change the URL to something like 10-michal-gabrukiewicz, or even just michal-gabrukiewicz. When a user changes their first and last names, save this as another field in the table as that (michal-gabukiewicz) and then do a find by that field.

that sounds good but then i need to maintain another db field ... is there no way for simple encryption? it would be okay for me to have profile urls like this

/user/4fh39dj3jd

Simple encryption is harder than Just One More Field ™

It would seem to me that if you think you need to obfuscate the id value in the url there’s likely a but instead of getting into that I’ll offer a possible solution.

require 'uuidtools'
class Post < ActiveRecord::Base

  def before_create()
    [self.id](http://self.id) = OpenSSL::Digest.SHA1.hexdigest(UUID.timestamp_create())
  end
end

This should be a drop in replacement and make it impossible to predict id values…

Michael Greenly wrote:

It would seem to me that if you think you need to obfuscate the id value in the url there's likely a but instead of getting into that I'll offer a possible solution.

require 'uuidtools' class Post < ActiveRecord::Base   def before_create()     self.id = OpenSSL::Digest.SHA1.hexdigest(UUID.timestamp_create())   end end

yeah but then i loose my id .. i dont want it to be extremely secure .. a simple xor encryption should be fine i think .. does someone has it in the pocket?

Is not firstname-lastname secure enough?

Ryan Bigg wrote:

Is not firstname-lastname secure enough?

yep it is and i would really prefer this .. but my problem is that i have duplicates

then id-firstname-lastname

Ryan Bigg wrote:

then id-firstname-lastname

damn you are right .. this was mentioned already before but i didnt recognized that this combination is okay .. when i saw the id i immediately thought this is wrong... but it works like this! thanks...

Quoting Michal Gabrukiewicz <rails-mailing-list@andreas-s.net>:

i am developing a community which has user profiles ... those are now accessible through an url like e.g.

/user/profile/10

the 10 is the id of the user within the database. now i dont really like the plain ID within the url because it is very simple to iterate through the users ..

How about restricting user profile so only a user and the admin can view a profile?

Jeffrey