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) }

http://en.wikipedia.org/wiki/Brute_force_attack

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. http://en.wikipedia.org/wiki/Residual_risk

  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