49

A little background info here: I'm a self-taught web developer with very little experience outside of html/css, and the company I work for has hired a third party web development team to design us an e-commerce site. Anyway, I was beta testing the site today using the TamperData Firefox add-on, and I found two major design flaws which both involve HTTP headers.

The first flaw was that when our site asks the user to choose a freight option (ground, express, etc.) the site passes the calculated freight value back to the server in an HTTP header. By manipulating the header, I was able to modify (see: erase) the freight value and so the backend interpreted the calculated freight value as 0, and so it didn't charge me freight!

The second flaw, however, is far worse... When the total product value is calculated and I "checkout", all of the transaction information (CC#, CVV2, Expiry, $ total) gets passed to a third party merchant processor via an HTTP header. Once again, I used TamperData and was able to manipulate the header so that the $ value being sent to the merchant was something trivial (I choose $1 for the test).

The fact that I -- with absolutely no experience in website security or server side coding -- was able to find these severe flaws has me completely scared, because what does that say about the programmers who designed this? Sure, they will probably fix these two issues somehow. BUT, If sending credit card data in a plaintext HTTP header seemed like a good idea to them, will their new solution realistically be any more secure? What if there are other, completely separate attack vectors that I missed?

Thus, my questions for you:

  1. Given the information above, what steps would you take to avoid these security holes? (so I know what to request our programmers to do)

  2. What books, sites, and/or resources are available so I may teach myself about web security, and how to do actual penetration testing? It will take some time for my company to arrange for an outside security audit, and in the interim I want to fix as much of the site as possible.

UPDATE:

As I said in a comment below, I am interested to know exactly how secure it is to transmit the payment info in an http header to the cc merchant (we are using an https connection if that matters). Can third parties eavesdrop or intercept these packets? And if they can, is that a realistic scenario, or is it highly unlikely? I ask this because I don't yet have a good understanding of how transmitting data via HTTP headers works, at least on a technical level.

This question was IT Security Question of the Week.
Read the Aug 12, 2011 blog entry for more details or submit your own Question of the Week.

11
  • Was this a custom-developed site from the ground up? Or are you using some kind of e-commerce subscription package?
    – Bryan Agee
    Commented Jul 27, 2011 at 5:55
  • 9
    Bummer. Sorry to say it, but that cash is probably what I would call 'tuition.'
    – Bryan Agee
    Commented Jul 27, 2011 at 6:04
  • 24
    I just re-read the Q. Your development team passes card details in HTTP headers? This solution is easy. Fire them. Hire someone who understands PCI-DSS compliance. Oh, and just use an off-the-shelf e-commerce platform next time. Commented Jul 27, 2011 at 7:44
  • 15
    Have you considered a job in penetration testing? You seem to have the right mindset for it, and it pays a whole lot better than self-taught web dev. Given a bit of training, I think you'd probably be quite effective.
    – womble
    Commented Jul 27, 2011 at 9:04
  • 1
    I'm confused. It's very rare to send that type of information in HTTP headers however whether it's sent in the header or body is mostly irrelevant. Secondly, it's usually the server that sends credit card information to the credit card processor so a buyer's browser never even has access to those communications. The server should control all of the communications and should never trust information provided by the client. Commented Jul 28, 2011 at 18:29

9 Answers 9

37

A couple of suggestions:

  1. Don't build a site from the ground up, unless a new kind of e-commerce is your secret sauce. There are plenty of solutions out there that are tried and true—Ebay, WordPress with a shopping cart plugin, Drupal with plugins, etc. Rolling your own is a quick way to get hacked.

  2. Be sure to redirect to a secure payment processor before collecting any card or identity information. Both PayPal and Google Checkout offer great portals with APIs that make it easy to sell stuff safely, and redirect back to your site.

  3. Many of the hosting companies (GoDaddy, Volusion, etc) offer turn-key setups, so that all you have to do is fill a catalog, pick a style, ship stuff and go to the bank.

2
  • We are already using a 3rd party merchant processor, so if there was a way that we can securely communicate with them using some industry standard method for transferring cc info, I would be interested to know. (However, I am 90% sure that we cannot redirect the user to a merchant hosted processing page; we probably can only communicate with their backend)
    – Moses
    Commented Jul 27, 2011 at 6:18
  • 2
    @moses, why would you not be able to redirect to a merchant for processing? It really helps you avoid shooting yourself (and your customers) in the foot....
    – nealmcb
    Commented Aug 1, 2011 at 14:36
13

My advice to you is: hire a security company to do penetration testing on the product when it's finished. If possible, get a security requirement in the contract with the developer, so they will be obliged to fix all security issues as if they were normal bugs (read: for free). This may sound like overkill, but imho if the last year has taught us anything it's that webapp security should be default by now.

You can come up with some security requirements yourself, and use the ones in the other answer(s), but you won't be able to do a full security audit on it if you're not educated in that field. So don't rely on that. You may fix the payment system, but leave some large SQL injection or uploaded file execution unpatched.

11

Any user supplied data can be tampered with by the user. You should count yourself very lucky if these are the only problems in the site. But they are indicative of a lack of quality in the delivered product.

Having worked with companies from simple part-time mom+pop webshops up to large financial institutions, the one thing I've learnt is that IT outsourcing very rarely works in the interest of the business. As a minimum you must have experienced IT staff taking an active involvement in specifying the contract for the product as well as specifying the functionality. I'll bet the contract in this case goes on at great lengths about costs and delivery times but has very little terms regarding quality, compliance and warranty.

The 2 flaws you described, although both arising from data tampering, are quite different. In the first case, since presumably there is a session in place, there is no need to send the data on a round trip to the browser in the first place. But for both issues have you checked that the changes are not picked up later in the processing?

The solution to the both is the same - store the amounts (or details required to calculate the amounts) on your server and check that the amounts returned by the browser are not different when operation completes. e.g. when generating the freight options page, store the metrics used to calculate shipping (e.g. weight) then when you get a shipping method and amount back, calculate the expected amount from the stored weight and supplied shipping method.

While it may seem simpler to not bother returning an amount from the page directly, or to just ignore this amount, if your site has already told the customer on the page what the shipping amount will be (e.g. with a javascript calculation) you need to ensure that, for a legitimate transaction, the same value appears on the customers bill!

i.e. these are both trivial problems to resolve.

But as you've implied, sending credit card information via a non-secure channel is a very serious, possibly illegal, oversight. And its the third and by far most serious flaw.

All software has bugs, but taken together these cast very serious doubts over the competency of the developer, and suggest that you've just scratched the surface of the problems with this product.

BTW: there are very few sites I would enter my credit card details on - even with SSL. There are several high-profile companies which provide a complete solution for payment processing e.g. Paypal, Worldpay, Google where the merchant has no direct visibility of my credit card details.

For learning more about website security you'll find good introductory material (and some more advanced stuff) looking at sans.org and owasp.org

7

The answer is "OWASP" or "Open Web Application Security Project", at http://www.owasp.org. These guys are the standard for understanding the typical vulnerabilities (like this) that plague web applications.

You also asked "what does this say about the programmers" that they could have such trivial bugs. The answer to your question that is that most web application programmers don't really understand what's going on. They don't believe that hackers can change HTTP headers in transit.

Currently, in the news, there have been a lot of high-profile hacks ("LulzSec"). These kids aren't doing complicated hacking, but the simple stuff you did, such as editing HTTP headers when submitting data.

5

I'll answer the question in your update first.

Transmitting CC data over HTTPS connections is (if configured correctly) fine. If you look at most E-Commerce setup (amazon etc) then whenever they take CC data that's how it's done. That said the bit about HTTP headers is odd... Usually the data would be transmitted as part of a form submission or (and this is a bad idea) as part of a GET request in the URL, but I've never seen it actually transmitted in the headers before.

On the issues that you've discovered, as a couple of other replies have mentioned, from what you've said it looks like what the developers have done is not implement proper server-side checking of data supplied by the browser.

All information (purchase totals, freight amounts) should be re-caclculated server-side after submission from the browser, to ensure that it's not been tampered with.

If you're getting a full E-Commerce site coded for you, I'd recommend that you get a independent security assessment completed before it goes live. As you're dealing with Credit card data, you'll need to do that anyway as you'll be in-scope of PCI.

2
  • Just like I asked @midnightmonster, I am a little confused about the security of our ecommerce transaction because if a hacker uses a proxy server between the client and our server, all of our communication will be in the open as plaintext TCP transmissions. Shouldnt we implement encryption our data on the backend before sending it so we arent reliant on HTTP over SSL encryption? Is this a major threat we should be worried about, or is this such an unlikely attack vector that we should just ignore it.
    – Moses
    Commented Jul 28, 2011 at 16:09
  • If the data is transmitted over SSL then the proxy wouldn't see anything other than encrypted data (unless they terminate and re-establish the SSL connection). If they terminate the SSL connection then the user will get a warning about the certificate, as the name on the certificate won't match with a valid issued cert without quite a lot of additional work by the attacker. Ultimately if the attacker can intercept all traffic from a client to your site, the client's probably somewhat at risk, but there's not a great deal you can do about that... Commented Jul 28, 2011 at 16:25
5

What HTTPS does, and -all- that HTTPS does, is stop 3rd parties from getting involved in the middle. It stops man in the middle attacks, 3rd parties reading or changing the data as it is transmitted, and that is it. (Edit, since I can't comment on another post: You are still vulnerable to proxies that the end user trusts. https keeps an -unknown- 3rd party from -silently- pretending to be you, but your user can still collaborate with a known proxy. He'll get warnings indicating that a man in the middle attack is happening, and he can choose to disregard those and permit it because he's the one controlling said attack. Demonstrate to yourself easily by setting up Fiddler and telling it to proxy https connections (not the default, and it warns against it, but it will do it for you if you tell it to. [6]))

So you have two main potential points of problem: Either end of the connection. You could have a problem in your server code, or a problem with a malicious client (not necessarily the current user) (A 3rd class of problems is possible if you bounce between http and https at any point after authenticating the user or giving them a 'session', session hijacking or sidejacking - 3rd party gets enough information during the http part of the conversation to initiate their own authenticated https conversation. "Firesheep" is a tool for demonstrating this.)

The best overview I've seen for keeping up to date on what you need to know is the Open Web Application Security Project top 10 list. [1]

On the server side, you need to make sure your code is checking for malicious input:

  • "Sql Injection" ("little bobby tables": [2]) (chiefly defended against by consistently using "bind variables", but see OWASP for more)

  • "Cross Site Scripting" or XSS (if you take input from a user, such as a product review or their name, and display it to another user, user 1 can steal information about user 2 by entering malicious information such as some bad javascript). Chiefly defended against by using a whitelist of valid things for a user to provide, escaping all output that a user provided (hard to do perfectly/consistently), and not letting users enter html (This is one reason why things like Markdown, the editing language used on stack overflow, exist. The other reason is that html is too easy to screw up - unclosed tags ruin the rest of the page - and hard to parse/validate.) Again, see OWASP.

  • lying users / tampered data. Tamperdata is a good way to get an idea what users could do. Other tools for lying are a rewrite proxy like Charles web Debugging Proxy [3]. You defend against this by never trusting user-provided data. Do calculations on the back end. If you have a nice dynamic shipping calculator in javascript or something, that's nice for updating the user, but repeat the calculation on the server instead of trusting the $ value they came up with.

For your credit card processor scenario, is generally a fine idea because they deal with security and you don't need to worry about storing card numbers. What you need to do is secure the data being sent to them. You could do this either by

  • Talking to the processor directly from your server instead of redirecting the user to their site. Has its own set of trust and security problems, your users have to be willing to give you their credit card info and believe you when you say you won't screw it up. Requiring users to trust you might reduce sales, might be not worth it so don't necessarily insist on this option.

  • Maintaining a product catalog with the processor so they know your pricing.

  • Signing any pricing information you send the processor so that it can't be tampered with.

  • Checking back with the processor after the customer has entered their data to make sure it's right.

Unfortunately, it looks like it's actually par for the course for the processors not to support product catalogs or signing prices. For example, I don't see it as an option with Paypal "Website Payments Standard" [4]. The only answer in those cases is a post-processing reconciliation step - check the amount paypal says you got against your order data saying how much the amount should be, and cancel any order where it's wrong. This is a bad option because needing to re-contact the user is expensive and time consuming, and you'll be getting into arguments where people lie and blame your system (and sometimes they might not even be lying - bugs are possible.)

Example of option 4, Paypal Express Checkout has a verify step: you're supposed to directly call 'GetExpressCheckoutDetails' before 'DoExpressCheckoutPayment' to do a confirmation page. [5] So I'd push for something like that - user enters payment info on a 3rd party site, then you contact the site directly from your server and verify the information for the user's confirmation page.

Good luck.

(As a new user here, I'm limited to 2 hyperlinks.)

[1] OWASP top 10 list: https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

[2] Little Bobby Tables SQL Injection: xkcd.com/327/

[3] Charles rewrite proxy: www.charlesproxy.com/documentation/tools/rewrite/

[4] Paypal 'Website Payments Standard' variables, note lack of signing options: merchant.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_Appx_websitestandard_htmlvariables

Then look at 'how it works' tab and note lack of 'they go back to your site for confirmation' step: merchant.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=merchant/wp_standard

[5] Paypal express checkout (see diagram where -your server- talks directly to paypal for confirmation page info): https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_WPECIntegration

[6] Fiddler's page on HTTPS: http://www.fiddler2.com/fiddler/help/httpsdecryption.asp

2

Yes, the fact that you're using HTTPS makes all the difference. The only reason the info appears to be clear text to you is that you're using Tamper Data, a browser extension that lets you play with your own POST data before you send it over HTTP(S). No one else but you and the gateway can read that info, or at least, they're no more able to than on any other secure site in the world.

The card thing is really No Big Deal. It's actually a pretty smart integration with one shortcoming.

See, whenever you touch credit card data, you become liable for a bundle of PCI compliance stuff, even if you don't store that data. It's still commonplace in this industry to handle that badly. But whatever payment gateway they're using has some support for you maintaining control of the checkout experience while not actually receiving or transmitting card data--a great thing for PCI compliance. So the form is on an HTTPS page on the merchant's site, but instead of posting to the merchant's app, it posts directly to the gateway. The gateway communicates status with the merchant via a synchronous HTTP request or signed data in a redirect URL, and the merchant's software processes the transaction without ever seeing card data.

This is the Right Way to do it for a site that doesn't get some compelling advantage out of building the infrastructure necessary to be PCI compliant. Done this way, PCI compliance requires just the trivial SAQ A. The only problem with this is that either the gateway does not support (sadly, the most common case) or the developer did not implement signing the transaction details on the merchant side.

To fix this, your developer needs to implement signing the transaction amounts if your gateway supports it, or else you need a backend process that, whenever it hears about a new transaction, checks with the gateway to make sure the right amount was paid and flags the order if not.

2
  • But wouldnt our app be vulnerable to hackers using a proxy server to act as a man-in-the-middle between the server and client? The proxy would force the HTTPS connection to revert to TCP-level relay that transmits in plaintext. In my mind that is the one shortcoming. While I theoretically understand that this attack can happen, I dont understand the logistics of how it happens. So is it our implementation thats vulnerable to proxy servers, or would a proxy server make even PCI compliant sites vulnerable?
    – Moses
    Commented Jul 28, 2011 at 15:39
  • 1
    HTTPS connection won't send the data in plain text. But you could have a proxy that speaks HTTPS. So I think I'm contacting foo.com, but it's really evil.com. They open their own HTTPS connection to foo.com with my data and then relay foo.com's response back to me. But my browser has a list of trusted cert authorities, and it won't let me contact evil.com-as-foo.com over HTTPS because evil.com's SSL cert isn't for foo.com or isn't trusted. The proxy scenario can be worse with server-to-server communication since programming libs don't always check for valid certificates, while browsers do. Commented Jul 28, 2011 at 17:13
1

The vulnerabilities you describe are unfortunately common, but thankfully easy to fix. As to your question, no, sending any data over headers is not secure. To do this securely, here is what you should do: 1) Generate an encryption key on your server (public/private) 2) at checkout, have your system (server side) validate the data the user has input against known good values, where possible. 3) Have your server generate a post request instead of the headers. CC and CVV should definitely be encrypted, else you aren't being PCI compliant. At no point should any of this data ever be sent back to the client.

As for security testing, I can help you there as well. I run a service which is very low cost and will find the majority of issues like these, as well as help you fix them. I also host numerous articles on how to code securely and how to spot common security vulnerabilities.

For web scanning - see https://www.golemtechnologies.com for security articles including how to correct these kinds of issues: https://www.golemtechnologies.com/articles

Good luck! and feel free to contact me if you want specific help.

-1

Ain't no shame in the homebrew app game.

Consider adding a crypto signature, like an HMAC hash, parameter to data you sent the client and expect to get back unaltered. When reading the data back check the hash sig of it. Your cc gateway should also let your crypto sign key purchase parameters like price in a way that prevents tampering.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .