PCI Compliance and the PHP Developer
PCI stands for ‘Payment Card Industry’, but to many people it’s a shadowy set of standards imposed by a secret international cartel champing to bury the unwary soul with back-breaking regulations and legal woes.
The truth of the matter is much more boring and pedestrian. In reality, PCI is a set of security guidelines drawn up by a consortium of credit card companies and industry security experts to govern how applications should behave when handling credit or debit card information. The card companies impose these standards on the banks who then impose them on those of us who operate e-commerce sites and the like.
In this article we will dispel a couple of persistent myths about PCI, take a 20,000-foot look at what PCI encompasses, and then zero in on those requirements that are most closely associated with coding in general and PHP specifically.
Not surprisingly, there are a number of myths surrounding the PCI standards. One such myth is they are like rules of conduct for the mafia, not written down anywhere so they can be interpreted anyway you want. That, of course, is not true. For a full statement of the PCI standards, all you have to do is go to pcisecuritystandards.org.
Another myth is that PCI security standards only apply to the “big guys” like banks and major retailers. They apply to every single person who accepts card information to pay for things. If you’ve written a site in PHP for your mother to sell her famous lemon pies, you have a system that falls under the PCI guidelines.
A third myth is that if you follow the PCI standards then you’ll be protected from malevolent hacking and your data will stay safe. That would be nice of course, but the fact is that the PCI standards are guidelines and ideas, not specific techniques (they have to be vague to fit all architectures and platforms). Obviously, the more attention you pay to security, the smaller your chances are of being hit, but anyone can be compromised. You will be viewed, both legally and consumer-ly, better if you have at least tried to meet the PCI expectations.
Finally, PCI is not something you do once and then breathe a deep sigh of relief. The standards calls for you to do a PCI review once a year, so this is something that is ongoing like quality assurance efforts or listening to your spouse.
The simple truth is that PCI is something that every programmer who works on an app that touches credit card data, no matter how small, needs to be aware of. Yeah, that’s why dealers only take cash.
The PCI standard is composed of 12 basic requirements. The standard is updated about every two years, and in between a variety of guideline documents are released that are more specific and deal with a certain subset of the PCI world. For example, in February 2013, the PCI people released a white paper discussing PCI and the Cloud. These special reports are also available from the PCI web site.
As we will see, many of the PCI requirements are more network oriented, but what is the point of talking about this stuff if you don’t walk away with at least a basic view of full PCI? The requirements are:
- Area 1 – Build and Maintain a Secure Network
- Requirement 1 – Install a firewall to protect your environment.
- Requirement 2 – Do not use vendor default profiles or passwords.
- Area 2 – Protect Cardholder Data
- Requirement 3 – Protect Stored Cardholder Data.
- Requirement 4 – Encrypt Cardholder Data that is transmitted across open, public networks.
- Area 3 – Maintain a Vulnerability Management Program
- Requirement 5 – Use and regularly update anti-virus software.
- Requirement 6 – Develop and maintain secure systems and applications.
- Area 4 – Implement Strong Access Control Mechanisms
- Requirement 7 – Restrict access to Cardholder data on need-to-know basis.
- Requirement 8 – Assign a unique ID to each person with computer access.
- Requirement 9 – Restrict physical access to cardholder data.
- Area 5 – Regularly Monitor and Test Networks.
- Requirement 10 – Track and monitor/log all access to network resources and cardholder data.
- Requirement 11 – Regularly test security systems and processes.
- Area 6 – Maintain an Information Security Policy.
- Requirement 12 – Maintain a policy that addresses information security.
Some of these items are related to policy decisions, namely the decision to set up policies that spell out exactly how you make an effort to protect card information and ensure the overall security of your network and applications. Other requirements relate to the network itself and to the software that you can use to protect it. Some of them deal with the design phase of the process, how you structure and set up your app. Hardly any of the requirements deal with code at all and none of them describe specific programming techniques that are recommended to keep you safe. To keep things relatively short I’ll restrict my sarcasm and wisdom (it’s a 70:30 mix) and focus on the last two groups.
Requirement 2 – Don’t Use Vendor Defaults for Profiles/Passwords
In many ways this is almost a no-brainer. Security people have been telling us this since the dawn of worrying about things. But it is surprising how easy it is to just take the default account and password (especially when you first install things and everything is very ‘test’) on many of the pieces of software we use, MySQL to name just one.
The danger here is increased because the majority of us build our applications around some base pieces of software rather than doing the whole thing from scratch. It might just be a package we use to handle encryption and key storage (see below) or it might be the framework for the entire app. Either way, easy to remember, easy to implement: don’t use default accounts.
Requirement 3 – Protect Stored Cardholder Data
Most of the high profile retail site hacks that I can remember involved the theft of card or other data that the site was keeping, so I would rank this as pretty much the most important part of the PCI standard.
Obviously, any card data you store should be encrypted. And you need to do a good job of encrypting it. For those who know a great deal about encryption, you know that doing a good job of encrypting data means you have done a good job of managing the encryption keys.
Key management revolves around the problem of generating, storing, and updating the keys used in the encryption process. Storing them can be a big problem because you want to make sure that someone can’t get into the system and steal the keys. Management strategies differ on how to divide and separate the key into multiple parts; if you want an introduction to key management, I would start with this whitepaper by Securosis and then go from there, although be warned that the water gets pretty deep pretty quickly.
Of course, if you’re using a commercial product to handle encryption then you can leave the key management to them, although you want to make sure their process is solid and that it fits into your approach. Most commercial products are developed with PCI in mind and so would be built in accordance with the PCI standards, but it still doesn’t hurt to double check.
Also, the task of protecting data will become a lot easier if you minimize, or even eliminate, the amount of data you store. That is, card holder data could be anything from their name, birthday, card number, expiration date, card verification (CV) code (the three or four digits on the back or front of the card), etc. The fewer items you keep, the less you have to encrypt and the smaller your liability. Fortunately, this is one area where the PCI standard is pretty specific by specifying exactly what data you can and can’t keep. You may keep the card number (PAN – Primary Account Number), the card holder’s name, the expiration date, and the service code. If you do keep the PAN, then you must mask it if you are going to display it, with the first six and the last four digits being the maximum that you can show. You may NOT store the PIN, the CV code, or the entirety of the magnetic strip.
The question you have to ask yourself during the design phase is how much of this stinkin’ data do you really want to hang on to. The only real reason to keep it is that you want to provide your customers with an easy experience the next time in. And you can hang on to the birthday so you can send them a friendly little come on about birthday time. All that data has to be encrypted and protected, so make sure you are getting some solid business use out of it.
Requirement 4 (to encrypt any data being transmitted) is sort of part of this, but I am going to consider that part of the infrastructure and not dwell on it.
Requirement 6 – Develop and Maintain Secure Systems and Applications
This is the requirement that is related to code. Not to specific functions or classes, but at least making sure that you follow the general security standards and try to make your stuff somewhat bullet proof. So, you simply use coding techniques, regardless of the language, that do not open your application to obvious hacks. For example, you try to prevent SQL injections by taking precautions when you accept form data, you try to block XSS, etc. For more information on avoiding some of the more common security problems, refer to some of the other articles that have been published on SitePoint (this and this plus other articles available if you search by “security”).
Requirement 7 & 8 – Restrict Access & Unique ID
Both of these things relate to the way you access the app and so lie somewhere between coding and design.
Requiring a unique ID for each visitor should be no problem unless – you happen to let people sign on and shop via a guest profile. I can think of a couple of sites off hand that allow you to do this, and of itself it is not evil, but the use of group profiles is dangerous and you have to take extra pains to make sure they don’t have much authority. In general, you should strive to set up unique IDs, even if the ID is not one that you save. For example, you can let people sign on as a guest but then immediately create a unique profile behind the scenes for the event.
We also want to restrict physical access to the card holder data. This might be a nod to the future when we’ll be able to shrink people down to a sub-microscopic size as in Issac Assimov’s Fantastic Voyage and inject them into the storage device to get at the 1’s and 0’s of the card data… or it may also relate to things like locked server rooms, badges for all visitors, not letting anyone get close to the backup tapes, and that sort of thing.
Requirement 10 – Track and Log all Access to Resources / Data
Finally, don’t underestimate the importance of tracking and logging everything that accesses either a resource or the cardholder data… and I mean everything. Events that should be logged include signing on, signing off, data access; data updates, really anything that involves a resource or data element and you think might be useful as an audit trail or as evidence at a criminal trial. You must implement a secure log, review the log daily looking for trouble, and keep the log for one year.
For PHP users, it would be beneficial to get familiar with the PSR-3 logging standard that has come from the PHP-FIG group and provides a uniform yet flexible way to set up your logging. Rather than get into this here, I would recommend Patrick Mulvey’s introductory article.
I guess the one thing I want to really stress is that PCI is not icing. Its part of the flour of creating apps that work with credit card data. If you’re writing an app that does take in such data, it applies to you whether your clients know it or not. Most of it is above the coding level, but it is real and something you must still pay attention to.
Image via Fotolia