3

I'm maintaining a low-traffic shop website that stores credit card numbers in the database. This isn't right (or even legal I believe), so I'm changing the way the numbers are stored.

The way the site is structured, the credit card information page posts to itself, validates data, stores the data in the db, and then redirects the user to a cc verification page where the cc is verified and the order is place. After that, they are redirected again to an order completion page. Anyway, to get the cc number from the cc info page to the verification page, I was thinking about using session, but I'm worried about vulnerabilities and am trying to look into them (I'm reading this ref. and this one). I can store the cc number in session, retrieve it on the next page, use it, and unset() it, and it is gone within seconds (also note, these pages use SSL). Something like:

cc info page:

session_start();
$_SESSION['card_number'] = $_POST['cardnumber']; //please tell me if there are vulnerabilities here setting directly from $_POST
...
header(sprintf("Location: %s", $insertGoTo));

cc verification page:

session_start();
//retrieve $_SESSION['card_number']
unset($_SESSION['card_number']);

Only the card# is being stored in session, the rest of cc info is in the database. Though I don't think someone can do much with just the cc#, it should still be secured as much as possible.

Given I use session.use_trans_sid = 0 and session.use_only_cookies = 1 (where session identifiers are only handled through cookies and not URLs (not sure why I need both)), and given my use of this specific session variable, is this code vulnerable to session fixation? Would it be beneficial to regenerate the session ID (after or before?) I set the cc# in session in this case? I'm guessing yes, and since the protocol is SSL by this point, I'm also guessing that once the session has been regenerated, I'm protected as far as the SSL will get me?

So, my main question is, following these guidelines with my site, would a skilled attacker have a reasonably difficult time fixating/hijacking session to get a user's cc# for the amount of time it exists (roughly 3-15 seconds)? If not, how, if possible, can I get it to that point?

Community
  • 1
  • 1
Nick Rolando
  • 25,879
  • 13
  • 79
  • 119
  • `session.use_trans_sid` makes php automatically modify the output html, adding the session id to certain urls. `session.use_only_cookies` makes php only accept session ids from a cookie header. Without this setting, php looks for and accepts it via cookie, post, or get, in that order. – goat Jan 27 '12 at 01:53
  • also, google for php session fixation articles. I don't think you'll get an answer here that does proper justice to the topic. – goat Jan 27 '12 at 01:56
  • @chris So are you saying I don't need `session.use_trans_sid = 0`? – Nick Rolando Jan 27 '12 at 03:18
  • you generally want it off if security is a concern. You said you didnt know why you needed both directives, so I explained their difference. – goat Jan 27 '12 at 05:41
  • @chris I see, thanks. I guess I don't understand why it would add session id's to urls if `session.use_only_cookies = 1`. It seems contradicting. – Nick Rolando Jan 27 '12 at 19:30
  • You're right, it would be rare to have both turned on, but there could be specific cases where you would want that. You might not want to accept a url sess id on the *current request*, but might want to add an id to urls for the *current response*. Also, you can manually tell php the sess id via `session_start($session_id_from_wherever_you_want);` in which case, maybe you got it from the url, but needed to implement your own custom validation logic upon it and the enviornment before you resume a session with that url id. – goat Jan 27 '12 at 21:24
  • @chris Oh okay. Thanks for clearing that up for me :) – Nick Rolando Jan 27 '12 at 21:46

2 Answers2

2

Even if the session was hijacked, the person could only get the CC number if your script is allowing the user to see the CC number, or there is a dump of the session on your site.

Also keep in mind that it can be unlawful to store CC numbers in a database in plaintext. If your worried about data theft, be sure to encode or encrypt all sensitive data.

Good luck!

Adam Fowler
  • 1,750
  • 1
  • 17
  • 18
  • Sorry for the late response. "Even if the session was hijacked, the person could only get the CC number if your script is allowing the user to see the CC number" - That is really what I needed to hear, thanks! – Nick Rolando Feb 01 '12 at 01:18
  • "or there is a dump of the session on your site" - What do you mean by that? – Nick Rolando Feb 01 '12 at 01:18
  • something like var_dump($_SESSION); where the contents of the session could be visibly seen by the user. – Adam Fowler Feb 01 '12 at 01:27
0

You should never store the card number at all. By default PHP stores the session in a file on your machine. If your machine was compromised someone could steal the credit card numbers from the session file.

What you should be doing is taking all the information and passing it straight to a credit card processor like Authorize.Net or using a service that allows the user to pay on a domain hosted by the service and then returns them to you with an auth code so you know they paid (PayPal has such a service, I know they aren't the best but there are others)

Capturing the information at all requires you to have at least some level of PCI compliance. Storing the card information at all requires a much higher level.

There's tons of stuff out there about PCI. Here's the wiki on it: http://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard

Cfreak
  • 19,191
  • 6
  • 49
  • 60
  • Agreed. Not storing credit card numbers at all negates the liability of a compromised system. I wonder why SONY Playstation stored them, and actually assumed that liability, when they got hacked a few months back. – Mike Purcell Jan 27 '12 at 00:34
  • Does the session file on the server continue to hold that information, even after I `unset()` it? I agree with you about not storing it at all. The original developers designed it this way and I am not too happy about it, as they could have easily done it within the same page. I guess the best thing to do would just be to integrate the two pages.. Thanks for you answer. – Nick Rolando Jan 27 '12 at 00:43
  • @Shredder No, after you `unset` a SESSION variable, that information is no longer in that associated session file, but its best to also use `session_destroy`, which destroys all data registered to a session. – Josh Jan 27 '12 at 01:41
  • Session files are encoded... its not like it can be easily decoded either. If I remember right PHP generates a key at runtime so session data on the disk should be secure... – Adam Fowler Jan 27 '12 at 02:02
  • @AdamSack That's awesome! Do you have any resources to back that up? – Nick Rolando Jan 27 '12 at 03:02
  • @AdamSack The key being generated at runtime would mean it would have the same key until the server is rebooted, which would give attackers all the time in the world to figure out that key. But at least it is encrypted. But regardless, I `unset()` the cc# right after it is used, so it should be ok. – Nick Rolando Jan 27 '12 at 17:37