views:

40

answers:

2

My question is on how to preserve data during the redirect when using the PRG Pattern on my forms. Specifically, I'm wanting to use this in an ecommerce application. I have three options of storing the data over the redirect, and I have concerns with each. I'm hoping you guys may be able to help me work through this issue:

1.) Store Data in URL String

I can store the data as an encrypted string passed in the URL. This is great in that I don't have to store credit card information, but my worry is that (and maybe I'm wrong) Google Analytics might cause the credit card information, though encypted, to be indexed and show up in search results. Hopefully I am wrong in this concern and can use this method, since it's the easiest.

2.) Store Data in Sessions

I could store the data in a session, but I'm worried some users won't be able to use sessions because of cookies being disabled, which would limit the usefulness of the application. Additionally, I would be storing encrypted credit card information in the session and PCI Compliance says that I am not allowed to store the CVV under any circumstances.

3.) Store Data in Database

I could store the data in a database, which would solve the compatibility concern I have with sessions -- but I'm still left with the problem of not being allowed to store CVV numbers under any circumstances.

It seems that passing information through the URL is the best method when using the PRG pattern. I'm just worried that Google Analytics in the page might index the query string in the URL. Even though the query would be an encrypted and unreadable form of the credit card information, I still wouldn't want that to show up on anything. Hopefully I am incorrect in thinking Analytics would store and index that information.

Please advise, thanks for your help.

+1  A: 

Ley's say you pass the credit card information through the URL.

The only way crawlers could index a page with the CVV is if the URL the user was redirected to after post submissions somehow leaked. You say you encrypt the credit card information passed in the URL, but the details of how this is done are crucial.

If you just encrypt everything with the same key and just decrypt the URL information when the page is requested and show it to the user for confirmation, it's certainly not enough. It would still not be enough to e.g. allow that confirmation page to be displayed only once – since there are not that many CVV numbers, any user can trivially try all the combinations and see what they encrypt to. So I'm not even considering complex cryptanalisys solutions.

A possible way I see this could be done would be to generate a long random key (or as long as the information you're encrypting; since it's not that much data and you can use symmetric encryption in that case), encrypt the data with that key, and set that key as a secure and short-lived cookie on the client (all over https, of course). That way, even if the URL leaks, only that user will be able to decrypt the credit card information.

This also solves the problem that you may be logging the requests in your web server; since very rarely are cookies logged, an examination of logs will also be insufficent to retrieve the credit card information.

Artefacto
Art, thanks for this -- great advice. I am using encryption such that the same post data would look different each time, having the same key but a unique iv for each encryption. I have added the synchronous token pattern using sessions, so anyone showing up with a well formed URL would be rejected because they lack the proper session. Still worried about Google Analytics auto-indexing my pages, not crawlers (not sure Analytics even does that). Thanks again.
swt83
A: 

Disable Google Analytics for the pages where you'll be passing this information and make sure you have a cert on all pages which have the information. It's probabaly worth you using some basic encryption too.

Here's what you could do if you're going to send in the URL, it'll give you an extra layer of security:

$text   =   '464945645667567564564';
$key    =   'highlysecurkeyhere';

// step 1: encrypt (you can then send this through _GET as urlencoded)
$iv         =   mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB), MCRYPT_RAND);
$encrypted  =   mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CFB, $iv);
$encrypted  =   urlencode($encrypted);

// Recieving end, decoe then decrypt.
$output = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, urldecode($encrypted), MCRYPT_MODE_CFB, $iv);
echo $output;
Kieran Allen