Encrypting URLs

This article is also available in the following languages:
By yuri.salame
Encrypting URLs is not very SEO friendly but when this is not the aim you can easily encrypt everything to avoid tampering when normal checks have been forgotten.
My current situation has forced me to encrypt my URLs, but how to do that globally and sometimes not do it at all? Desktop applications had the security of never showing which parameters they were using within the application but since users can fiddle with the querystring webapps had to add that extra amount of security.

When a user can't view a certain record you just lock him with credentials, database queries and such for verification purposes. If he has permission to access a record like this one : http://www.somesite.com/record/44 he can easily change the querystring to http://www.somesite.com/record/87 and access a different record. You lock him outside record 87 by querying the database or some other method but when an application gets too large with many programmers sometimes these checks within a controller might be forgotten.

A simple change on the webroot/index.php and a couple of encrypt/decrypt funcions on the bootstrap can resolve this issue.

On the app/webroot/index.php right before the $Dispatcher is instanced call your decrypting function passing the current url being accessed.


$url = do_decrypt($_REQUEST["url"]);
$Dispatcher = new Dispatcher();
$Dispatcher->dispatch($url);


On your app/config/bootstrap.php add the decrypting and crypting functions.


function do_crypt($url)
{
    return 'url-'.base64_encode($url);
}    

function do_decrypt($url)
{
    if (substr($url , 0 , 4) == 'url-')
    {
        $url = substr($url , 4);
        return base64_decode($url);
    } else {
        return $url;
    }
}

The Base64encode is used just as an example here but you can do any kind of crypt here, Blowfish, DES, TripleDES, MD5(db-based), 2-Way, etc...

Since the URLs that are crypted have the "url-" prefix if an url does not have this prefix then the original URL is used. This solves the problem of having just some of the URLs encrypted.



Comments

  • Posted 08/13/08 01:47:33 AM
    I just tried this on a controller and it works:

    Controller Class:

    <?php 
    function encoded($id null) {
      
    $id base64_decode($id);
      
    $this->view($id);
      
    $this->render('view');
    }
    ?>
    It simply uses /posts/encoded/MQ== to get /posts/view/1
    Although I don't know if there's any repercussions for doing it like this.

    It probably would be better to generate a random string, save it in the table and use it for access. I've seen Google use something like this for showing rss feeds for the user's calendar.
  • Posted 08/01/08 12:29:49 PM
    But I really have to recommend uuids in this case. Not only will you not have to mess with the routing but you can still have user readable urls which makes the whole app much more friendly. Proper use of acl's can also stop people from accessing numeric id's while still allowing you the advantages of numeric ids and allow you to not rely on security though obscurity which encrypting the url (even with sha256 or whatever) is still doing. That link can still be shared and copied and googled for, while tying it to a user account's access control list will deny access to anyone who doesn't have access.

    There's an ACL Management Plugin here that is an awesome way to get started.
  • Posted 07/31/08 03:31:34 AM
    I have copied the

    $url = do_decrypt($_REQUEST["url"]);
    $Dispatcher = new Dispatcher();
    $Dispatcher->dispatch($url);

    in my webroot/index.php file before $Dispatcher
    and then i have copied the following code
    function do_crypt($url)
    {
    return 'url-'.base64_encode($url);
    }

    function do_decrypt($url)
    {
    if (substr($url , 0 , 4) == 'url-')
    {
    $url = substr($url , 4);
    return base64_decode($url);
    } else {
    return $url;
    }
    }

    in my bootstrap.php file ...
    but it is not working ..
    Please help me..
  • Posted 07/17/08 03:29:56 AM
    And what's the benefit of that? Everyone could base64_decode the URL and modify the records ID and then encode it again, so, accessing different records would be the same result in here. Bad solution, sorry ;)

    A much better would be to generated UUIDs and put them in the URL or use a one-way encoded string for your records identication, e.g. md5 or sha.
    • Posted 07/29/08 04:09:25 PM
      And what's the benefit of that? Everyone could base64_decode the URL and modify the records ID and then encode it again, so, accessing different records would be the same result in here. Bad solution, sorry ;)

      A much better would be to generated UUIDs and put them in the URL or use a one-way encoded string for your records identication, e.g. md5 or sha.

      as I said :

      "The Base64encode is used just as an example here but you can do any kind of crypt here, Blowfish, DES, TripleDES, MD5(db-based), 2-Way, etc..."

      Personally I used a combination of 2-way with BlowFish but thats just me.

      Please read carefully the article before criticizing.

Comments are closed for articles over a year old