Keeping Private Customer Data...Private?
"I chose 1024-bit PGP encryption with a long passphrase. I use the Cryptix java package to handle the encryption from a Perl script (the reasons for this are legacy related, but I'm in the position where I can start clean if need be -- a Perl-only solution would be great).
The thing that makes me nervous is the secret key being stored on the machine that houses the database. The reason for this is so that our billing staff can handle the recurring billing. (They have a web interface where they must enter the passphrase to gain access to the credit card information.)
I have realized for a long time now that if someone gained full access to this machine, they could fairly easily run a brute-force attack on the encrypted data, if they found our secret key on that machine. But when we recently worked on our privacy policy, this potential problem became more important.
What changes could we make to our setup so that we can encrypt/decrypt the credit card information on the same machine that houses the data, while making it as hard as possible to decrypt the credit card data assuming the entire machine was stolen (or cracked)?
We are a very small company. How do "the big boys" handle these things? What is the best book on this particular subject?"
While this setup may work well for credit card numbers, what about setups that will protect other personal information like a customer's address and phone number? Would such information be practical to obfuscate in such a manner?
If work for a big bank in Canada (about 3 million clients), and you would be surprised to know that out databases are NOT encrypted in any way...
In fact the sole security rests on the passwords and the physical access to the machine.
But our servers are in a secured building, administered by IBM (you should see what it takes just to be able to enter the computer room, let alone trying to stay 1 minute in front of a console without someone asking you what you are doing there...)
I've done something similar before (though it was passwords, not credit card data) and the trick is to not store the secret key anywhere, especially on the server that stores the data.
I coded a server component that could decide whether a requester could view an encrypted datum (for example, if the requester authenticated correctly) and decrypt it using a key stored only in memory, that had to be entered by a human being to start the server. The humans who could administer the server memorized the key. A small enough amount of data was stored that changing the key was feasible.
This server was in perl, but the encryption/decryption code was in C; I used blowfish (libblowfish) and also stored the key in a C buffer pointed to by a perl scalar, and used the mlock() system call to prevent the key from being swapped--an alternative might be to use OpenBSD where it is possible to encrypt the swap area.
Anyway, I hope that gives you some ideas. Any form of storing or recording the decryption key reduces to storing the credit card numbers in plaintext, so you should avoid that.
demi
Ive ran across this problem myself several times.
According to VISA rules, the merchant is NOT allowed to store the cardnumber - its the property of VISA.
To get around this, I dont store the card. I store its SHA1 hash signature. This is great because you're guaranteed to get a match on the card's record - but you dont have to store the cardnumber itself. This also enables great negative database checking without liability to the merchant. You've got the sig - thats all you need.
The key storage you're referring to is an old problem. The key is never secure as long as it's in software (software can be cracked, reversed,
analyzed...I dont need to explain this). The only secure way is to store it in hardware somewhere.
You answered your own question: you don't put the decryption key on the same box.
You put it on another box, close all of the ports, and have a simple protocol running over something low-level which you trust like SCP or a PERL socket reader.
Your "co-host" stores the secret key, and does all decryption: the main host passes it a datum to decrypt, the co-host decrypts it, and passes back the cleartext.
The key never leaves the box, and the co-host should erase it's copy of the key and shutdown on any unexpected network activity (like an attempt to log-in). If you're really paranoid, have it also look for patterns in the access and die if anything unexpected show up - or return bogus, flagged test data (i.e. a list of bogus credit card numbers in stead of real ones).
Does that answer your question?
Hexayurt - open source refugee shelter,
A commonly used solution in high-security environment is to isolate the database machine from the network. I.e no network card. You then connect the database machine to the data processing machine via either a serial cable, parallel cable or similer that doesn't have a network stack on top of the driver.
You then have to create a client/server/queue manager on both ends.
Your security problem is now reduced to the functionality of the client/server that talks over the cable and performs requests on the database.
(Assuming of course that you can control access to the console)
A bit of effort, but it works.
echo '[q]sa[ln0=aln80~Psnlbx]16isb572CCB9AE9DB03273snlbxq' |dc
And even more importantly - if you must store them, shuffle them off to a machine that is not on the Internet.
At my old company, there was a system which handled new CC number entries. As part of a nightly process, they were moved into a database on a separate machine which was only connected for that window of time. All of this was on top of standard security measures. So the biggest risk was having the "temporary" entries compromised.
Many big groups don't emply the level of security you already have. Most bank 'security' is password protection and physical access protection. When break-ins happen they are not published; banks and credit unions are broken into quite often, and they pay to keep it out of the news. The unfortunate truth is that for big companies, it is cheaper to pay for damage from break-ins than it is to get good security to begin with. With the level of security you already have, look into business insurance. Tell them the precautions you have already taken and ask what would get you a better rate. (You would probably be a good risk for Insurance.) Implement those things, and have the insurer audit you in advance to make sure everything is up to snuff.
//TODO: Think of witty sig statement
As with most security related topics, depth layered solutions are best. Of course, design your network and connectivity with least access in mind--i.e. the database server itself is never directly accessible via the Internet, or even your first layer of permimeter defense. Typically, only http and https are externally acessible, with perhaps a few others like DNS, and FTP.
Usually your database will either be accessed by your web servers directly, or through an application server. Limit access to your database explicity to these addresses, through both the database configuration, and, if possible, IP-level configuration (like iptables in Linux). For each client connecting to the database (be them web servers or application servers) have then use unique password keys (and users, too, for that matter.)
Finally down at the application layer (we've done network, and server layers so far) you need to be more careful than ever. First, do the obvious, don't store sensitive material (read: credit cards) in plain text ANYWHERE. At list build in some kind of cipher key (crypt, if nothing else) that will encode the data in the database. If possible, you may want to look at more elaborate schemes for storing data in such a fashion. Beware, this is the piece of the puzzle that many will spend a lot of time focusing on, which is good, but not the whole shebang. Also note, any fields that you store encrypted, you will not be able to use easily as an index field.
Another oft forgotten place to focus on, is in the tools that you use for manipulating and storing the data. Everything above is worthless, if you have a careless programmer who writes a utilitiy that doesn't sanatize user input prior to executing an SQL query. A tremendous amount of the hacks you see out there are due to tools like these that are very vulnerable to misuse--since they were designed to have the ability to access your data, your security measures are for naught.
Make sure your programmers understand how the data is being stored both in the database, and the computer (ie. buffers, sanatized user input fields, etc...)
These are by no way complete, just thoughts of things I've had to deal with in the past while facing similar issues. Hope they help.
-buffy
It's not unusual for a merchant to ask for your credit card to process the refund. So, they ask for that again, and it's compared against a hash generated from the original order. Tada, easy as pie.
If you bill a customer's credit card, you are required to keep that credit card information on file so that you can reverse the charges and/or provide information on charge traces that may be requested by the customer.
There's an implict social contract between the parties when a credit card is used - the contract is that in exchange for providing a good or service to you with nothing in the way of security other than reliance on a banking infrastructure, I will be allowed/required to keep certain private information about you so that I can validate my accounting records of our transaction on demand.
Keeping this kind of info is not being "up to No Good", it's fulfiling my obligations under the social contract.
Our credit card info is stored encrypted in our Oracle database.
No one accesses the credit card info directly - we generate reports for billing staff. When credit card info is sent across the net (to process charges), we use secure sockets (as does everyone I'm sure).
The only machine that knows how to decrypt is a weblogic app server with the key, running on Solaris.
The database is on one virtual LAN, the webservers on another, and the app servers on a third.
We have PIX firewalls to keep out intruders, and our boxes are physically locked down in a cage.
In addition, our hardware topology is based on Windows 2000, Linux and Solaris. You would need to take advantage of security flaws in all three OSs in order to be able to traverse our site.
We make sure the passwords are not words or phrases. Numbers, funny characters, and letters.
The holes in our system are:
1) On weblogic, the connection info to the database is out in the open in the connection pools.
2) Billing staff need to be careful with how they handle paper reports. Perhaps we should only show the last 4 digits of the CC number when generating.
3) We refresh our QA environment once in a while. I have to be sure that I wipe credit card info, passwords, and email addresses from the QA database. While it's fairly secure as well, no point in leaving it around.
No system is perfect. So long as they are encrypted, on a machine that has the latest security patches, the machine is in a secure environment, and the passwords are "strong", you can sleep at night. Most of the large credit card thefts have been against systems that violated one or more of those rules.
you have reveiled thier new security strategy after the month long security audit they did.
-- Knowing too much can get you killed, but knowing who knows too much can make you rich.
You can find this also here:
:)
Following Text authored by Albert Langer not me, posted to ZCommerce mailing list on Fri 09, Jun 2000 . Still very valid:
<clip>
Warning: Following ideas are "off the top of my head". Not verified.
Q. "Where do I store the decryption key so that the cracker who snarfs the database file can't get it (just in memory somewhere?), and yet have the system be able to boot itself, including having the key, without human intervention?"
A. "Using a 'one time' fast key in a client cookie".
Details:
1. Generate single Public/Private key pair off site. (Slow but only done once).
2. Store only the Public key on web server.
3A. Store Private key very securely on internal site with controlled and audited access etc.
3B. Or better still, immediately destroy it. Losing only the functionality marked * below.
(Above are common to several previous responses. Following are new.)
4. Compress each CC card as received to shorter equivalent bit string (eg convert the parts that are card type to enum, remove checksum, convert remaining ascii digits to large binary integer and concatenate with the enum. This makes the cookie below smaller, also removes some redundancy.
5. Use public key to generate and store encrypted copy of compressed CC number on web server. (Fast). Do NOT store or transmit to internal site, except on specific secure request with audit records maintained at web server as well as internal site. Use same precautions as would be used for storing plaintext CC numbers or private keys.
6. Generate XOR of encrypted copy and plaintext on server. (Very Fast).
7. Store the XOR in long term client cookie (expiry no later than CC expiry date, or add expiry).
8. Destroy plaintext of CC AND the XOR on webserver.
9. Steps 4, 5 and 6 MUST be carefully designed to leave no trace of plaintext or XOR on web server, eg in virtual memory paged to disk etc etc.
10. Step 7 MUST be designed so web server cannot store cookie in client unless transmission protected by secure transport (https).
11. Step 7 SHOULD be designed so client cannot transmit cookie to anybody other than the same server and with the same secure transport (possibly impossible and a key flaw).
<clip>
See the link provided above for benefits of this approach, this post is already too long
This is where S/N really comes out. It's obvious that many people on here haven't actually done e-com, or if so, not seriously. To clarify for others talking out the ass. The person needs to do recurring billing. You can't just get on VisaNet and say "bill that guy again". The card number needs to be stored. They also need all the billing address and phone number. This needs to be done for AVS. If you don't know what AVS is and you posted in the thread you're part of the noise. Not having all the info costs merchants real money. There's more to writing a good CC Number system than being able to patch a web form into Signio/Verisign.
Good ideas, seperate Database on a seperate machine. One way encryption systems. Big keys to limit brute force. You can do it in house all with Perl, or you can use several off the shelf packages that allow recurring billing via a reference number. However, few shrink wrap packages are Unix friendly. Most tend to be Windows (ugh) based.
If you were to do it yourself combine several forms of security. Place the DB on a seperate physical network. Dual nics in machines that need to talk to the DB. Give the machine an non-routed IP range. An extra firewall isn't a bad idea either.
Don't forget DB User Level security. Seperate logins for everyone. Limit what they can SELECT, UPDATE, INSERT, and DELETE. Most DB's have column level security. For instance you can give an employee rights to INSERT or UPDATE the cc number field, but not select it. If you can use SSL on the DB transport use it. Billing persons shouldn't need to see anything more than the last four digits of the CC num. That can be stored in a seperate field.
You might also want to consider seperating the CC Number DB from billing DB. Using a ref idea. Again, you can never be too secure.
You should also be looking at application security. A couple posts have talked about putting a serial link between the billing app and the credit clearing DB. It's not a bad idea, but it only takes a couple lines inserted into your perl code to start trouble. You should be looking at tripwire systems as well.
Just because you're paranoid doesn't mean they aren't out to get you.
Comment removed based on user account deletion