The second post in my series from the darkened room; sometimes I walk away.
This engagement was a pure web application penetration test. The new client was an online retailer and the story starts and ends at the pre-test phase. They contacted us to perform a web app penetration test against a single URL. They initially wanted to spend no more than two days on the test, which would have been a day of testing and a day of reporting. The application contained in excess of 500 dynamically generated pages, five different payment mechanisms (one of which was to take bitcoin) and a user management system. With the size and complexity of the system, I estimated 14 days to fully test in line with PCI-DSS Req 11.3 but the client simply wasn’t having it. It was two days max, that is what another penetration testing firm had already quoted and if we wanted the business then we would have to match it.
What followed was one of the most difficult discussions between testing and sales. Sales wanted the business. Testing wanted nothing to do with it. In the end our CEO put in a call to the client and politely explained that to do the test justice he would need 10 days minimum to test the site to PCI-DSS standards. He understood that the client had been quoted two days and suggested something a little different to the client. We could do it bounty style. We would agree £10,000 for a proven critical risk issue, £7,500 for a proven high-risk issue and so on. That way, if there was nothing found then nothing would be paid. In the end we walked away from the job. Doing a good job is always better than doing a quick job.
A month or so passed and the new client came back to us. They had had the two-day pen test performed by the other party but were not too happy with the output from the test. They had addressed all the findings and now would like to take us up on our bounty style test. Now the client made a little mistake, in the email trail was the invoice from the other testing company and the report. It looked ok and told us what they had fixed. Could we rise to the challenge? Commercials were signed and a start date was set.
Ryd and Peter sat down on a cold and wet English winters Sunday morning and went through the job. One thing stood out as a viable attack vector and again, OSINT helped. The reconnaissance and intelligence gathering phase of testing is so very important. It told us one thing that would help immensely. Their web server has PUT enabled and the scripts directory was writable. After a few hours of experimentation, we knew that there was some extra protection player in play here and we were unable to create new files. We could however modify existing files. What followed was a "you are kidding right?" moment and our two testers sitting down for a cup of tea.
"Let’s go for the most game over event for a PCI test, steal the cards. But safely"
"That's a pretty sick idea. But look at the source, they are checking the hash of the file."
"Not rand.js though, it isn’t being checked properly, typo."
"What if we fix rand.js for them too, it sets the encryption salt."
Some minutes later, hashes of the transactions were being sent to one of our servers via HTTPS. That’s devastating, but could this be built on? Yes, was the answer. The following day their account manager had the conversation with the client to inform them that we had two Critical Risk issues (stolen card numbers and customer account takeovers) and two High Risk issues (HTTP PUT enabled and blind SQL Injection). It is fair to say that the client was extremely unhappy. Having just had a penetration test, how could these issues have been missed? From Peters point of view:
"The initial vulnerabilities, while easily detected by a competent level of reconnaissance, were missed by our commercial vulnerability scanners. We ran Nessus, NeXpose and OpenVAS against the target and these all missed the issues we identified. There were a couple of opensource tools that run manually identified the initial issues, as did our tool set but it was down to the testers experience and imagination to come up with the attacks. In the end, the only thing that was identified by automated tools was the HTTP PUT vulnerability. We had to manually trawl the source code of the site and test a lot of iterations to find a way to leverage the vulnerability. I still think we could have gone a lot further in the attack. We were able to mirror and capture all the card transactions, so the attack was viable from the financial crime viewpoint. Further, we were able to take over users accounts for newly registered users as we could set the random string used by the encryption salt function for user data to whatever we liked, rendering all encryption reversible to us.
This was a great example of a firm doing most things almost right but not seeing the value of skilled attackers. What started for them as a tick box exercise soon turned into a real penetration test. In all we spent three days on the test to complete the proof of concept attacks.
As ever, we only had to be lucky once and, on this job, we got four hits of luck.