1

If I have a website and the URL is www.example.com/mainpage.cfm?id=0123&app=2, how can I hide the id=0123 and app=2 so the user won't be able to change these variables?

I am looking at a complex program written by someone before me and he is passing these variables from page to page through the URL. I am just looking for a quick fix because I don't want to rewrite this entire program.

Fish Below the Ice
  • 1,273
  • 13
  • 23
BringQBasicBack
  • 119
  • 1
  • 12
  • How are the variables being passed? anchor tags? cflocation? meta refresh? – Dan Bracuk Aug 08 '14 at 16:18
  • 2
    Any time data is being passed from the client to the server, whether using GET (url variables as you described) or POST (submitting a form, for example) users will be able to change the data. However, if this is information that needs to be tracked from page to page, you could look into storing these values in the SESSION scope. – Scott Stroz Aug 08 '14 at 16:22
  • Dan - He is populating the links in a loop and adding an A href tag and adding the variables. Then on the next page he writes a query and uses the url.id. I was trying to avoid session variable since there are over 150 pages, but that might be the only solution. – BringQBasicBack Aug 08 '14 at 16:30
  • 1
    This is one reason why I rarely ever use integers as IDs any more. I prefer UUIDs. It is very difficult to guess another ID when using a UUID – Scott Stroz Aug 08 '14 at 17:18
  • Be careful with the session scope. With tabbed browsing, sometimes those change in ways the developer did not anticipate. – Dan Bracuk Aug 08 '14 at 17:20
  • About ten years ago one of my co-workers wrote a custom tag called linkwithform that did this. For the most part, we choose to not use it. In any event, the way it works is that on the sending page, variables from the anchor tag are copied as hidden form fields and the form is submitted. On the receiving page, all form fields are copied to the variables scope. – Dan Bracuk Aug 08 '14 at 17:29
  • If tabbed browsing causes issue with your session variables, you are doing it wrong. – Scott Stroz Aug 08 '14 at 18:53
  • 1
    Dan - hidden form fields can be manipulated on the client side so the issue would still be present. – Scott Stroz Aug 08 '14 at 18:54
  • possible duplicate of [Encrypt IDs in URL variables](http://stackoverflow.com/questions/4480908/encrypt-ids-in-url-variables) – Raedwald Apr 22 '15 at 06:10

5 Answers5

1

Here is how you encode it:

#URLEncodedFormat(Encrypt(id, "#key#"))#

The id is the variable, and the key can be anything (used as a certificate to encode and decode).

To Decode:

cfset url.id = #Decrypt(url.id, "#key#")#

Again the key variable would be the same variable as the one to encode.

Fish Below the Ice
  • 1,273
  • 13
  • 23
Sovr Sov
  • 196
  • 3
  • 17
  • 3
    This may obfuscate the information, but does not 'hide' it or prevent client side changes to it. – Scott Stroz Aug 08 '14 at 17:17
  • Have you reviewed the encrypted values? Short, unsafe characters and visble patters. I recommend avoiding encrypt/decrypt. SAMPLE: 85 = "+^( 86 = "+^$ 87 = "+^ 88 = "+^\ – James Moberg Aug 08 '14 at 22:55
  • 1
    *I recommend avoiding encrypt/decrypt* I suspect you meant avoid using encrypt - with the DEFAULT algorithm ;-) As Adobe's own docs say that "algorithm" is the least secure, and is only included for backward compatibility with legacy apps. It should not be used for anything IMO. However, *real* encryption algorithms, like AES, Blowfish, etcetera, are perfectly acceptable. – Leigh Dec 09 '15 at 23:22
0

I think I found a better solution.

Using (CGI.SERVER_NAME, CGI.HTTP_REFERER, 1) lets me know if anything in the url has changed. I can apply this as follows:

<cfif FindNoCase(CGI.SERVER_NAME, CGI.HTTP_REFERER, 1) eq 0> 
<cfabort> 
<cfelse> enter code here... 
</cfif>
BringQBasicBack
  • 119
  • 1
  • 12
0

How about using the hashids library. http://www.hashids.org/coldfusion/

In addition to ColdFusion, the library is available in JavaScript, Ruby, Python, Java, PHP, Perl, CoffeeScript, Objective-C, C++, Go, Lua, Elixir, Node.js and .NET. This makes it extremely easy to use with other languages and even dynamically generate IDs on the client-side.

<cfscript>
hashids = new Hashids(salt="this is my salt"
    ,minLen=8
    ,alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");

id_to_hash = listtoArray("1");   // try "1,2,3" and "3,2,1" and "1,1,1"
writeoutput('original = #arrayToList(id_to_hash)#<br>');

hashed_id = hashids.encrypt(id_to_hash);
writeoutput('hash = #hashed_id#<br>');

unhashed_id = arraytolist(hashids.decrypt(hashed_id));
writeoutput('unhashed = #unhashed_id#<br>');
</cfscript>
James Moberg
  • 4,360
  • 1
  • 22
  • 21
  • Why should not I use ColdFusion built in encryption functions? – user3427540 Aug 11 '14 at 07:10
  • The default algorithm, CFMX_COMPAT, is "coldfusion only". This means that the hashed values can only be encrypted & decrypted by ColdFusion and no third party libraries. If you wanted to open up access to a third-party, use AES. This will generate a code with a minimum of 32 characters. – James Moberg Aug 11 '14 at 15:38
  • When using hashids, the integers are converted to a single hash. The code is short (a minimum length can be assigned) and you can add a salt value. hashids won't generate curse words, doesn't use characters that look like numbers, can retain numeric sort order and there aren't any collisions; all hashes are unique. I've started using this with my password reset scripts because I prefer short URLs. – James Moberg Aug 11 '14 at 15:40
0

What is the problem with people changing the ID?

Certainly, they may find themselves on pages that don't exist, and you need to do some cfif generic catching to prevent errors, whether your pages are stored as files associated to the numbers or as files in a database.

You could make keys for pages that were otherwise nonsensical, like just a straight hash with simple salting of the number (like hash("1blueplug") becomes a79ea61e3b69d54a008772bcaf0fb398. Store the hash in the database or as filenames or whatever. Since they won't know your salt (blueplug here), they have no real way to get to pages they shouldn't be.

I wouldn't be bothered by my users changing the parameter on my website and disrupting their own experience. Pages should have necessary checking like to make sure that a form was really submitted.

Beyond that, what sort of pages are they able to access that's doing more harm than disrupting their own experience? If the pages they're accessing are some sort of security concern (administrative or other users' pages), it's time to consider a new application.

Regular Jo
  • 5,190
  • 3
  • 25
  • 47
  • I am worried about SQL injection. I dont want someone to edit the url and drop a table. Here is an article that explain what the user could do by changing a url variable. http://www.imperva.com/resources/glossary?term=sql_injection Note the line that shows adding "DROP TABLE Products" to the end of the url – BringQBasicBack Aug 13 '14 at 14:08
  • 2
    This is a separate from obfuscating the ID. SQL injection could be performed even if an invalid ID is passed. To protect yourself from this, use CFQUERYPARAM, validate all inputs and/or install an application firewall (like FuseGuard). http://helpx.adobe.com/dreamweaver/kb/protecting-coldfusion-server-behaviors-sql.html https://foundeo.com/security/ – James Moberg Aug 13 '14 at 15:44
  • Like Mr. Moberg said, you can do, and should do, things like CFQUERYPARAM or Where pID = #val(url.pID)#. Val converts any non-numeric number to 0, so trying to say "?pid=7 DROP TABLE.." converts the value to 0, they get no page. You can also, depending on what kind of control you have, create a database user that doesn't have permissions to perform certain types of statements as an additional layer of security. It's not a substitute for safe scripting, just an additional layer. – Regular Jo Aug 14 '14 at 12:22
0

Here is a quick and dirty way to do it, I learned this once a long time ago, but the original web page that described it was taken down. So from memory here it about the same thing:

    <cfset email = "test@myemail.com">
    <cfset algorithmkey = "typeanythingdoesnotmatter123">
    <cfoutput>#email#</cfoutput><br>
    <cfset test = #encrypt(email, algorithmkey, "CFMX_COMPAT", "HEX")#>
    <cfoutput>#test#</cfoutput><br>
    <cfset emailagain = #decrypt(test, algorithmkey, "CFMX_COMPAT", "HEX")#>
    <cfoutput>#emailagain#</cfoutput><br>

If you save the above into a CFM template you'll get the following output:

test@myemail.com

650CEDC7328BA59A21980793329A73F6

test@myemail.com

Unless the person attempting to hack the value knows your algorithmkey = "typeanythingdoesnotmatter123" it will be hard to decipher the value and thus replace with anything that would work in it's place for those fishing around for id's or something from other accounts.

  • You may have missed it, but that is what the [accepted answer](https://stackoverflow.com/a/25208711/8895292) from a few years ago does already. cfmx_compat is the default when no algorithm is specified. Though these days, cfmx_compat isn't recommended for encryption anymore. See encrypt docs for details. – SOS Jul 11 '18 at 14:10