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?
I think the first question these people should ask themselves is why they are storing their customers cc # at all? If you can avoid doing that, it's by far the most "secure" solution!
Websurfing done right! - StumbleUpon
augment your senses: http://sensebridge.net/
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 suggest you change your solution to run on Win2k.
Ah, yes, if you want to increase your security, run a Microsoft OS. And if you want to increase your protection against STD's, use condoms manufactured by Firestone.
You can run but you can't hide, except, apparently, along the Afghan-Pakistani border.
I wonder if this question (and the others mentioned) have anything to do with this recent IDG story.
Sinepaw.org: Grape Winos
create a new column called, say, PASSWORD, in the database, and throw some random junk in there, and hope the cracker wastes all their time trying to crack *that* ;)
It's 10 PM. Do you know if you're un-American?
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
On a related tangent, here's another question. Do you guys have any recommendations for a low end credit card purchase system requiring low or zero startup fee, but rather charging a per-transaction fee?
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.
I find it disturbing how companies seem to be rushing into Passport like systems that keep a large number of credit card #s and other sensitive data in a central repository, when no such system has ever shown to be reliable enough to justify the risk.
Frankly, I'd prefer to just keep typing in my credit card number, or have the info stored on my computer for my convenience. I don't like the idea of my personal data being permanently stored in a potentially insecure remote location.
In Capitalist America, bank robs you!
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
I would consider storing the numbers in Navajo. It worked in WWII.
Best Windows Freeware
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
PGP-encrypted SMTP relayed on an internal VLAN to a machine with the 'recipient' key, decrypt ONLY on the destination machine, encrypt ONLY on the Internet-facing machine. Perl classes for this exist and implementing it is therefore a question of writing the appropriate 'glue' for your site.
Internal access and usage is a policy issue. There is no way to engineer a usable solution whereby a user cannot write down a credit card number and expiry date and begin using it to buy stuff short of policy, enforcement, and legal action. You'll come up with some real Rube Goldberg schemes if you try, but fundamentally, if you must have human contact with the billing authorizations, you have a policy issue, not something you can ironclad by technology.
You will simply have to ensure that only trusted staff (eg. have a vested interest in the company's success) have enough access to do any damage. Technological solutions to social problems are a very poor fit and a very large time sink.
Sorry. We segregate authorization and billing where I work so that I don't have to jump through these hoops anymore. Small-order authentication is farmed out (and with it, the liability) so that our major customers are charge accounts with whom we deal personally in case of a problem.
Remember that what's inside of you doesn't matter because nobody can see it.
Anything put out on the internet should have no important data on it. Period. No connections from the internet (aka untrusted aka hostle) should be allowed to the box with the real data, other than those which are PROVEN to be needed, and secure. So:
internet -> firewall(1) -> web server -> firewall(2) -> database
So, you have 2 firewalls. One internet facing, and one (idealy a different vendor) from the DMZ to the internal world.
Also, you can set up 2 houses for the data. One (the one that the internet can get access too by proxy) should only cache the recent data. Hourly, or nightly, it should then be put into another server, from which the accounting department can run bills. Then this box (for accounting) should have no allowed connection to the rest of the world, save from the accounting department.
Oh, and the important data should be then purged from the internet proxy accessable database.
Zapman
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.
and I've implemented reasonably correct versions of almost all the others, so I am not just 'guessing' but offering observations from someone who's built several systems like yours.
You want accounts and you want them managed separately from billing. Physical security is what should realistically protect the private payment and identification information that relates to those accounts (eg. the substance to their metadata) so that day-to-day manipulations of orders are separate from month-to-month billing updates.
You simply must keep private info private and enforce it via legal and policy measures. No amount of technology will easily prevent misuse of your data. You could, however, experiment with CryptFS or StegFS to make it much more difficult for a physical security breach (eg. stealing the machine) to result in information leakage.
When I went back and reviewed the submitter's question I decided that I had focused on the wrong aspect of his question. One-way encryption (outside-to-inside) is important, and it can be keyed to the same database as customer account identifiers, without divulging useful information on a public interface. However, the primary measures for his company to take are still going to be policy (dissociating private customer data from public/unimportant customer identification data) and legal (physical security, pressing charges when anyone tries to circumvent).
Again, every measure I'm discussing above is something I've had to deal with in my job, and I am merely offering opinions as to what has worked best for us. I design my systems (at least at this point in my career) so that, for the most part, someone could steal them outright without greatly affecting our day-to-day operations.
Remember that what's inside of you doesn't matter because nobody can see it.
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.
Make sure the co-host is not networked at all; have the connection be a pair of RS-232 serial lines instead. On the line that sends the data to be validated, clip the wire that would allow signal to be transmitted back - (break RD, leave TD intact) to create a one-way signalling method.
Go/no-go decisions are signalled on the other link, either with simple sense carrier signalling (wire CD to DTR or whatever) or a very restriced set of allowed responses.
Programming the system is a pain in the ass since you have to use the console, but once set up it should be so simple it'll need no other maintenance than backup tape loading.
Any cracker who can figure out how to break your system when you have no net link is so much smarter than you, you're probably doomed anyway!
Just a summy post to collect most of the points above that are good ideas:
.. if you need the # for display on pages (like receipts), you only need to display the frist/last 4 digits for confirmation purposes, so only store those (encrypted). This is along the lines of minimizing the 'pot of gold' in a worst case scenario.
.. depending on the data's sensitivity (and CC#s are supermega sensitive), you can opt for various levels of hardware isolation of the box that stores the key, via a serial cable or something.
... everyone knows car crashes can happen, but being drunk during one is going to void any possible blame that could have been placed on people other than you.
- Use 'per record' encryption, where the records are encrypted each with a per-record unique key that is hidden from the outside (user-supplied is good, like a password, or if you need to decrypt without customer interaction, on a seperate box inaccessible from 'outside')
- You should have a method of 're-encrypting' records should a key(s) be compromised, to get the data safe as soon as possible after detecting comprimisation of your key(s).
- Dont ever decrypt - if you can get away with it, dont ever decrypt
- Isolation
- DONT ENCRYPT USING A KEY ON THE BOX ON WHICH THE DATA WILL BE STORED, or you might as well call your box a honeypot.
- make sure you use 'proofs' to verify the data, post encryption. Store the proofs on a box other than the data hosting box, so you can detect data comprimisation as soon as possible! (You could run a local data intergrity job nightly to detect mofified or currupted records.)
Everyone knows the worst can happen with computers - but if you did your best (and kept interested parties informed as to your efforts), then you wont/shouldn't be blamed if the worst happens. This is analagous to drunk driving
"Old man yells at systemd"
TrustCommerce has a great system called BillingID's where you can submit all your credit card info for storage on our secure Linux servers. You are given a handle that you can use bill the customer at any time through our cool GPL'ed client API. Retrieval of the CC info is impossible so even if your server is compromised the hacker can't get your credit card information. This lets you bill customers at your leisure but lets you offload all the extra security responsibility onto us. Security is, after all, what we do. </shameless plug>
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
It's easy; don't store the information. If it's not there, noone can steal it.
;)
Store the address, name, phone number, visit history, mother's maiden name, shoe size, whatever you want - but don't store the credit card number.
I'm quite happy with entering my credit card information whenever I purchase something. Knowing that this information will not be leaked to the next script kiddie who drops by - you simply cannot trust security at sites with dropping revenues, budget cuts, etc.
Clearly, the number one priority for many business sites today is to keep things running. Security is only a problem if it's broken. And that only happens if you're unlucky... Yearh right...
Am I pessimistic, or are you naiive ?
For example in dealing with encrypted passwords in a database... lets say I have a user database with encrypted passwords in it. (Could also be credit card info, etc.) For security purposes, I'd like to NOT decrypt any passwords for authentication, because that will place the password in plain text somewhere in memory, which is undesireable. Instead, for authentication, when the user supplies a password, I encrypt it and compare against the encrypted string in the database.
Same can be applied to credit card info. Once encrypted, you should rarely have to decrypt. Think of dealing with it from the standpoint of encrypting user input for comparison and validation against encrypted info in the database. This will save you from having to decrypt at all.
The other argument is "its not secure if its attached to the net". Basically, you should have the info stored on a separate database server with a direct cable link to the application server via a private NIC.
Skiers and Riders -- http://www.snowjournal.com
I agree. Mod the parent up.
Use a two-phase query system. The main network generates a request for CC #s, and that request is passed on to the CC number storing machine, using a serial cable with the two receive lines cut. The CC number machine answers the query and writes encrypted results to a re-writeable CD. Twice a day someone puts the CD in a computer connected to the main network and runs a program that checks that the results are reasonable. If they are, that computer puts the results in a shared directory. Then someone runs the program that uses the CC #s.
Maybe this is not the best system that can be designed, but something can be designed so that there is no networking connection between the CC number storing computer and the CC number using computer.
If someone breaks in to the main system, they get a maximum of only the CCs being processed that day.
An important feature of any security system is also to make the system difficult to hack from inside.
This problem (while common) is really not that difficult to solve, in your situation. Here's what you have:
Break the problem down, especially the flow of information, sensitive and otherwise, because this is key:
So, after sketching this down, here's what I've come up with:
- You'll want three servers:
- 'Net accessible web server, contained in a firewall's DMZ (demilitarized zone)
- sensitive data DB server (restricted access from DMZ, unrestricted access from 'trusted' source)
- 'trusted' web server (for employees)
- sensitive information flows to DB server via well-defined interface, but not back (see above posts regarding serial cables, restricted ports, etc.)
- auth info (success/failure) and de-sensitized information (last 4 digits, etc.) flows back to the 'Net accessible web server (to support e-comm apps)
- Open communication to trusted server (secure to your hearts content, see posts on policy & social problems above, key point: trusted server should mean trusted server)
- Employees access sensitive information via trusted server either from private internal net or VPN connections.
- Make it impossible for anyone to access your sensitive DB server from the DMZ (this should be easy to). Once you've accomplished this, your information is secure, regardless of what you do on the actual DB server
... sure, you can still encrypt the data in your database (you should) and all that, a few different methods are described above, but in essence, by restricting the flow of information and then segregating the information repositories based on that flow, you've taken care of your problem.
This type of system allows for updating of information in the DB as well, if you want to allow this, you'll want to design some kind of authentication mechanism between the requestor of the update (the user's password would work) and the sensitive DB server. Otherwise, a cracker could, potentially, corrupt your sensitive data (not really a big deal since backups are being kept). If this is the worst that can happen, you're sittin' pretty.Note: while this 'scheme' requires three servers, they don't necessarily need to be distinct (the one in the DMZ needs to be distinct, of course). The others, though - that's up to you, depends on your resources. Check out user-mode-linux if you want to logically distinguish servers on the same hardware. Encrypting the data files used for each user-mode-linux session should suffice to secure each session from the other, should the host become compromised (again, shouldn't be a consideration, this would only be done on a 'trusted' machine).
If anyone's more interested in what I've written down here, feel free to contact me via the contact info associated w/ my Slashdot acct.
Brice
--
WebProjkt
VP, Director of Internet Technology
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