“Hacker Safe” PCI Compliance in osCommerce?
Several weeks ago, I received a frantic call from an administrator of a site running a popular fork of osCommerce, saying he had 72 hours to fix dozens of vulnerabilities reported by ScanAlert–the company behind the “Hacker Safe” PCI compliance logo–or his right to display the Hacker Safe logo would be revoked. I ended up doing the job I was asked to do: I not only eliminated all of reported vulnerabilities, but in the eyes of ScanAlert, the site was now able to display the presumably more stringent Visa branded PCI compliance seal, which it hadn’t been able to do before. Although the customer was relieved and even downright ecstatic about the outcome, I was left with some very mixed feelings about ScanAlert, and the work I had done.
First, I’ll describe the solution I implemented, then I’ll blow a lot of hot air about my general misgivings about ScanAlert and my “solution.” And before we go any further, let me say that in no way am I implying that either osCommerce or PHP is inherently weak on security, so settle down already.
Becoming “Hacker Safe”
Upon receiving ScanAlert’s report, I immediately saw that almost all of vulnerabilities reported by ScanAlert were cross site scripting (XSS) vulnerabilities. Now, I’m not particularly knowledgeable about XSS attacks, but I really didn’t need to be to see what ScanAlert was doing and figure out how to strategize around it(!). Basically, ScanAlert was sending various GET and POST requests to the system remotely and scanning the response to see if they had successfully injected what could be malicious code in the response.
The administrator who contacted me assumed I would sift through the code and fix each error individually on a per case basis, which given the large number of vulnerabilities as well as the size and complexity of the osCommerce code base, would probably not get done in the 72 hour window. Even if I focused on updating just the core functions and classes in osCommerce, I am not sure I could have plugged every hole in time. Furthermore, such changes would introduce a tremendous maintenance burden whenever the site was upgraded to a new version of osCommerce, especially as the administrator had no real knowledge of PHP. And, given various constraints, that included the administrator’s reluctance to contribute any code he has paid for to open source projects, it didn’t appear practical to try to update the core osCommerce code and submit changes back to the project.
So, just to be clear, my goal really wasn’t to “fix” this aspect of osCommerce or even to make the site more secure necessarily, it was to achieve “Hacker Safe” approval in a given amount of time and do so in a way that could be maintained by the system administrator.
Fortunately, this fork of osCommerce had theme/templating capabilities, and the site was already using a customized template , which meant that I could inject the code into the main template script, and it would execute before any output was sent to the browser and “sanitize” any user input at that point. Because I would be injecting the code into a customized template that was already being maintained and accounted for in upgrades, I could add this code without adding to the administrator’s responsibilities.
Now, I thought I remembered that in PHP, a stock approach to preventing XSS when constructing the response is to use the built-in htmlentities() function, so I started there, quickly coming up with this basic approach:
function sanitize(&$input) {
foreach ($input as $key => $value) {
$input[$key] = htmlentities(html_entity_decode($value));
}
}
if (! empty($_GET)) {
sanitize($_GET);
}
if (! empty($_POST)) {
sanitize($_POST);
}
The reason I used both html_entity_decode() and htmlentities() together is because it became apparent that at certain points in osCommerce, htmlentities() was being applied to some values in the course of processing requests, so by calling html_entity_decode() (the result of which is the opposite of calling htmlentities()) on every value first, I could ensure that the values would be encoded in such a way as to be appropriate for input to htmlentities().
This approach plugged some holes, but wasn’t nearly enough to satisfy ScanAlert, so after some quick Googling, I came across a small PHP function designed to more aggressively scrub data against XSS attacks. I substituted that function for the htmlentities(html_entity_decode($value)) call above, re-ran ScanAlert and viola, no more XSS vulnerabilities! Not only did the site now have Hacker Safe approval, it now also had Visa PCI compliance, which it hadn’t had before.
Obviously, this approach is pretty generally applicable outside of osCommerce and could be adapted to work outside of PHP also with a little work. Even in the case of osCommerce, which does not follow an MVC approach in the least, I was able to find a point just prior to rendering the browser template where I could inject this code. It was effective in achieving PCI compliance, at least as judged by ScanAlert, and it might even turn out to be a quick and easy way to truly and effectively combat XSS vulnerabilities in general.
What did I really accomplish?
Although I have a decent amount of knowledge about, and experience with, both PHP and osCommerce based applications, you may have noticed that I am not an expert on Web application security, and this was my first brush with trying to achieve PCI compliance. Its a little scary that with no real directly applicable knowledge I was able to easily implement a solution.
From the beginning, the entire ScanAlert situation seemed sketchy. This site had been displaying the Hacker Safe logo for several weeks, telling customers that the site had been scanned, tested and certified. During that time, no updates were made to the underlying code, yet suddenly, more than 80 vulnerabilities were detected, and all but four were XSS errors.
Also, we were given 72 hours to fix the site, which was certainly nice of ScanAlert. Yet, anyone going to the site during that time would be told that the site was “Hacker Safe” even though there were presumably over 80 vulnerabilities on the site. I don’t know about you, but 80 vulnerabilities sounds like a lot, so, should we really be promising customers they are “Hacker Safe” in this situation?
As I read ScanAlert’s reports in more detail and discovered what they were doing, it was evident that other than port scanning, detecting XSS vulnerabilities is ScanAlert’s bread and butter. (It did detect an “SQL injection” vulnerability when it found a script outputting the results of the phpinfo() function in PHP. Presumably, from this output, ScanAlert’s software saw that PHP was compiled with MySQL support and dutifully reported that the database was “MS SQL”.)
So basically, when it came to the Web application itself, ScanAlert only really checks for one class of vulnerabilities, and this isn’t surprising when you realize that all ScanAlert does is probe the application remotely, and obviously, they don’t want to damage their customers’ sites, which significantly limits the effectiveness of probing for say, SQL injection vulnerabilities.
Yet in a Dilbertesque attempt to quantify the unquantifiable, ScanAlert claims that their scans account for 99.9% of all Web application vulnerabilities. (Interestingly, this figure was plastered all over the ScanAlert site at one time, and now I can’t find it anywhere…) Anecdotally, I don’t even think that ScanAlert can claim to account for 99.9% of XSS vulnerabilities.
But perhaps I’m being too judgmental, and looking at this situation from the wrong point of view. PCI guidelines were developed by the credit card companies as a way of reassuring customers that it was indeed safe to use their credit cards on compliant sites. In other words, its ultimately a marketing ploy, and ScanAlert is just taking this to an extreme. If your site is not PCI compliant (and this needs to be verified quarterly, I believe), the credit card companies may stop accepting your business until you get with the program, but there is no rule saying that you have to use ScanAlert or any other company. But you probably don’t want to scan your own site on a regular basis, so ScanAlert is just one of many companies willing to provide that service for you.
And ScanAlert supplies obvious value added services: they scan your site daily (presumably) and allow you to display a logo saying as much, so your customers can also have a false sense of security. ScanAlert claims that displaying the Hacker Safe logo translates directly into increased sales on your site.
And of course, this is ultimately what is boils down to, money. Whether or not your site is more secure it has the appearance of being more secure, and that’s what ScanAlert really sells. And if you display the Hacker Safe logo, you’re selling it too. The problem I have with this is that is relies on and exploits the ignorance of customers and even the site administrators. Before this job, I really didn’t know what was behind the Hacker Safe logo, nor did I care. I’m sure I simply felt reassured when I saw it.
And despite trying to educate my client with what little new found knowledge I had, I don’t think he fully understood all these implications either. So, despite having a completed job, a happy client and money in the bank to show for it, I am left wondering if this really was a successful job, or if I am merely a player in someone else’s game.
Is the site more secure now? Yes, to a point, many obvious holes were plugged. But even if the site is now 99.9% “hacker proof” that .1% is still probably plenty of room for a determined cracker.
What is even more disturbing to me is what this says about the security of the code that I (and probably you too) create. I don’t think I’m alone when I say that I am under considerable pressure to complete projects, which means adding features, functionality. Its my boss’ job to squeeze as much out of me as he can in as little time as possible. And its a full time job just getting that damn computer to do what it should do, I just don’t have a lot of time to protect against what it shouldn’t do.
And in all that spare time I get, I have to constantly continue learning my craft (reading about design best practices for example) as well as the keeping up with the various languages, libraries and frameworks to practice that craft. What, you think Ruby on Rails is the last framework you will ever have to learn? Ha! Some people probably thought that about Struts too…
Learning these tools and practices is interesting–dare I say fun–and leaves me feeling like I have improved my skills and made myself more productive and more valuable to my employer. Even if time wasn’t a factor, deeply educating myself about application security just isn’t as sexy.
I think our best hope for salvation in this situation is the fact that as open source developers, we don’t have to know everything and test it all ourselves. We can invest in collaboration, putting our security best practices into the code for our libraries and frameworks thereby benefiting from each others’ knowledge and hard work.
I’d be interested to hear others’ thoughts on this. What resources to you use to educate yourself and keep up to date about security concerns? What FOSS tools do you use to secure your code or check for vulnerabilities?

[...] stone mind » “Hacker Safe” PCI Compliance in osCommerce? — A pretty good story about those “hacker compliance” buttons you see on e-commerce sites. [...]
very informative post, thanks.. regarding the xss scrubber function, where did you include the function, and how was the osC code altered/integrated?
Glad you found this helpful.
This particular osCommerce fork had theme support built-in, and although I used it to create a customized theme for the site, I did this some time ago, and I have only a vague memory of how it works underneath. But basically, after each request is processed, the output is delegated to a version of catalog.php in the active theme’s directory, which in turn renders the correct output for the page/action. So I included the XSS scrubber in the very top of that theme’s catalog.php as described above. This way, I don’t clobber valid user input, which has already been processed by that point, so the underlying behavior of osCommerce is intact, but malicious input should be neutralized in the page output, where it would execute and create havoc. And because this modification is inside a theme that I was already maintaining anyway, I didn’t introduce any upgrading issues.
I hope that’s clear enough to be helpful. That XSS scrubber is nice isn’t it? I may not have any good ideas of my own, but I sure can copy other people’s good ideas!
I really enjoyed this article, and I hope to be able to put your solution to work on a site I’m developing for a friend that uses osCom for the cart. Unfortunately, I’m working off of the default template for osCom, and I’m not sure where I should include the scrubber (ie, will I need to insert it manually on every page, or is there a way it can be worked into an include? - I am NOT a programmer by any means). But thank you for a first step! I am going to try the old Trial and Error.
Thanks for the feedback Jessie. I think you want to find the catalog.php script, which ultimately controls the output the end user sees, and at the beginning of that, you should be able to insert the XSS scrubber as an include.
I am a little short on time at the moment, but if you are having problems implementing this, feel free to contact me offline at blogger@stonemind.net, and I will try to set aside some time to help you further.
Thanks for your comments on your experience.
I’m currently reviewing ScanAlert and PCI compliance. My company switched web hosts and therefor back-end programming. I rebuilt their shopping cart by hand based off things I learned from osCommerce.
Your gripes about displaying “hacker safe” bring up a good point about ethics. Is it reasonable to show “hacker safe” even when there are vulnerabilities detected? If I knew that, I’d probably have a different job.
Though, I did find other filters online for PHP to filter input and that’s always been the #1 rule I learned about web programming….
NEVER TRUST USER INPUT
This even means filtering the URL as it’s not uncommon to use $_SERVER variables that are based on URL information.
Anyway, thanks for sharing your thoughts
Good points, thanks for sharing them. I’d be interested in seeing the other filters you found, and hearing your opinions about how they compare to the one that I point to above.
Hi, This article was informative and I have been reading alot about SCAN ALERT lately.
Our company is about to emblazon the HACKER SAFE logo based on other companies conversion rate for customers. While I can see why they want to make more money, how does that translate if our customers end up with there info stolen anyway? It reminds me of snake oil salesmen promising a cure-all when there is none to be found.
What I find disturbing is that they are blatantly playing on the industries ignorance on the whole PCI compliance issue. Isn’t it your hosts responsibility to provide you with security? Last Fall many HACKERSAFE sites were exposed for their XSS vulnerabilities. The hackers/slackers.org folks were right on top of them and still SCANALERT promises what they cannot deliver, A GUARANTEE. There disclaimer would be the first clue.
Thanks.
I don’t disagree with your characterization, although I think that ultimately the blame goes back to the credit card industry that set the PCI standards in the first place. The ScanAlert folks are just capitalizing on the need that the PCI standards created in the first place. ScanAlert is playing the role that the credit industry wants them to play, and its the credit industry itself that makes the most money from this marketing ploy.
At the very least, there is enough blame to go around, even for developers like you and I who are pressured to play this game. Like I said in my post, even though I “succeeded” from the customer’s perspective, I didn’t feel good about the work I had done and the part I had played in perpetuating seeming misinformation. I tried to educate my customer, but I suspect he just didn’t want to hear it. After all, what was he going to do about it? Probably nothing in the 72 hour window, and he had his own business interests to worry about.
Nice article, ScanAlert has been calling me to setup with them. I found your article and now have a little more understanding of what they scan for. Little pricing for a logo.
Thanks
I placed the code:
function sanitize(&$input) {
foreach ($input as $key => $value) {
$input[$key] = htmlentities(html_entity_decode($value));
}
}
if (! empty($_GET)) {
sanitize($_GET);
}
if (! empty($_POST)) {
sanitize($_POST);
}
In application_top.php of my oscommerce store, is that all that needs to be done? Is that the right spot?
Nice article.
Thanks.
Dailce,
That code will help, and putting it in application_top.php will work I believe. The approach I ultimately settled on, that worked for me, involved using the script that I link to in the post above and placing the call to the code in a custom catalog template. Because I was already maintaining this template, putting it there didn’t create an additional maintenance burden for me, as it would have if I had put it somewhere like application_top.php.
I hope this helps.
Nice article, ScanAlert has been calling me to setup with them. I found your article and now have a little more understanding of what they scan for. Little pricing for a logo.
Thanks
Here is an article about recently discovered XSS vulnerabilities on HackerSafe sites:
McAfee ‘Hacker Safe’ cert sheds more cred
http://www.theregister.co.uk/2008/04/29/mcafee_hacker_safe_sites_vulnerable/
Sorry to repeat, but as others have said, this is an excellent and very timely article. I run the forums at BYTEmeCITY and our company is currently preparing to release it’s latest service, BYTEmySITE.
Since we use OSCommerce, actually more the CREloaded version and recommend it to our customers.
Additionally, we are also thinking of supplimenting our new website monitoring service with testing for hacker vunerabilities. Your article could not be more on track for us.
I realize that the work you did was for a customer. So you may be prohibited. But, if not, a complete “White paper” on how to step-by-step implement your fixes to OSCommerce would be of certain interest to many of us in the real world.
The fact is, OSC and it’s sister projects are great tools for small business use. On the other hand, in January of this year several of our clients where victims of hacker attacks. Since none of those hacked were more than mom & pop operations, no one actually ever expected to be a target of an attack. Unfortunately, size does not matter to a hacker.
In any event, thank you so much for sharing your experience with the world. We appreciate the insights, I am certian thousands more do also.
If you decide to write a paper, please, please do let us know. We would be pleased to promote it to our clients and the global merchant market.
John,
Repeat away! Seriously, thanks for the positive feedback.
As for implementation, I wish I could say I came up with a clever, innovative solution, but I really did just replace the call to htmlentities() in the sanitize() function above with a call to the indicated RemoveXSS() that Kallahar makes available on his site, which I link to in the post. That’s it: Hacker Safe compliance in 60 seconds or less.
(I wrote this over a year ago, and its still working.)
The trickiest part was where to insert the code. I inserted it at the top of a custom template, so it would be called after all processing, but before anything was output to the browser. That way, it was less likely to introduce a bug by changing a value before it goes into the database, for example, but it would scrub input before displaying anything in the browser. And because I was already maintaining the template, I didn’t add to my maintenance burden by injecting the code into core osCommerce code, which might get blown away in an upgrade.
I was working with the oscMall fork at the time. Its templating system placed template directories within /includes/template/ and the file I injected the code into was catalog.php (at the begining of the file). Its been awhile since I’ve seen CRELoaded, but I think it includes a templating system also that can be used in the same way.
Your white paper suggestion is intriguing. I’ll give that some thought.
Hello,
Read the article, examined several things regarding the posted code and here are my remarks:
1. This code html_entity_decode($value) won’t work well as you may run into cases where a different data type is passed via the global arrays (not string). Ref: http://www.php.net/manual/en/function.html-entity-decode.php
This should be straight forward I believe if you wanted to rectify, by checking the data types and apply the necessary conversion or recursion to the scan mechanism.
2. I do not agree with the approach of scanning the entire global arrays. I have also seen many other methods including the osC core that have the same flaw. In other words, scanning, parsing and try to “rectify” unknown variables. So for instance if we have a link mysite321.com/?joe_doe=5 your code will attempt to filter the joe_doe parameter ensuring that 5 is “valid”?. And the filter mechanism that is in place (this removexss function) is quite expensive in terms of resources. That brings up the next issue.
3. If you check the timings to parse each parameter, they can be significant and subject to the parameter length. I run a couple of tests using the $_POST array adding around 100 lines of text garbage in a form to just one parameter and then posting the form measuring the timings. Under a 3.2 GHz server running locally, with PHP5.x, Apache 2.x, MySQL 5.x I got around 100 mSecs latency parsing just this variable.
To summarize, issue-3 can be exploited by an attacker for a DoS, issue-1 can cause warnings and errors with the PHP depending what an outsider may decide to pass through the global arrays and expose information about the server. Also in this case it won’t filter anything as the functions expect each parameter to be a string.
As of scanalert, they insist for some reason that a site must filter form elements and get/post parameters and return the filtered results to the user’s browser! I do not agree with this. If you pass say a variable like above joe_doe=alert(document.cookie) why would I ever process it, filter it and propagate to the other pages? It’s insane.
Now on the other hand, if a parameter, is to be processed by the framework because it’s a valid form element, then I would process it internally (server end) and filter it accordingly. But, what I send back to the user’s browser is another story. I may well send him back exactly what he posted. The scanalert support ppl cannot comprehend this. They believe is an issue to be “fixed” for some strange reason. Along with other articles I read around the web from time to time. In other words if someone hacks his browser by altering the html of forms or links and therefore thinks he also hacked the server he must be right?. Or if he browses the web from a hijacked machine. Subsequently the server-end must rectify his hack attempts or clean up his system and so forth….., they got to be kidding me.
These remarks are for the long term so no offense for what you did to meet your client’s requirements. For a 72 hour notice to have the site PCI compliant.
Thanks for the detailed information, which should help those who want to make their sites more secure. As I said, my goal was PCI compliance, not more security per se, and what I implemented exceeded the PCI guidelines. But, you’re absolutely right, we should do better than this.
Hello again, just crusing the web and here i am again. I see that this discussion has advanced. The post by enigma1, is excellent. We need folks like that to jump on board and build solution sets. The inside knowledge is very clearly an asset to this discussion and any serious resulting solutions.
I have to say, that here at BYTEmeCITY we are very interested in this topic. Every day we get closer to moving past Beta on our newest project, BYTEmySITE and one of the things we are discussing is website security issues.
Back in January we and some of our customers suffered attacks on our websites. We prefer to avoid this happening in the future. And we think most people with a website would also like to avoid having it damaged by senseless hacker attacks.
That said, we notice the the cost of services like HackerSafe and others are very expensive. Some more than $2000 annually. Without arguing the effectiveness of such services. A debate held elsewhere.
What I see here, is serious people, thinking about serious answers, to serious problems. But, it would be even better, if solutions came from this discussion, ready to use, spanking hot solutions.
So, just a thought folks. Perhaps a non-profit, GNU solutions group, to focus on developing these great ideas into useful ready to install solutions for those who cannot otherwise use this information.
I know I could arrange the hosting space, free of charge for such a group. And, with a little promotion, the group could result in a growing number of programmers, adding to the project, while using the resulting products to make cash installing and consulting from the project resources.
Just a thought. But a beautiful dream.
Thanks for the kind words on my last post. But, truly this is great material here. Thanks for the opportunity to comment.