Of payment gateways and quality assurance



  • A client asked us to do a custom ASP.NET MVC website with some payment gateway integration. Some junior devs completed the website, client paid for it, then the client went away without even taking the site live. Fast forward 6 months and the client is back and wants a bunch of shit changed, including the payment gateway. The devs who originally did the work are now on other projects, so it falls to me to rewire the site. As I quickly find out, the client dodged a bullet by asking for changes...

    (Quick refresher on how payment gateways generally work: when you sign up with a payment gateway, they generate a unique key. You and the gateway are the only ones who know that particular key. When a customer submits an order through your site, you use the key and some other info (e.g. the amount being paid, client's name) to generate a hash (fingerprint), and send the hash along with the payment payload. When the payload hits the payment gateway, the gateway uses an identical algorithm to calculate a hash, and compares theirs to yours. If the two don't match, the transaction isn't processed.

    Once the gateway has processed the transaction, it then sends a notification - including another hash generated similarly to the previous one - back to your site. The onus is then on you to verify that the gateway's hash matches what you calculate - only if they match can you assume that the notification is valid, i.e. not an attempted attack.)

    Anyhow, I find the payment gateway code and quickly realise I'm in trouble. Dependency injection is the new hotness in our company (welcome to 2004), so everything has an interface. The payment gateway interface is 100% designed around the old payment gateway's API, thus negating any benefits of using an interface. The interface is also so specialised that creating a mock implementation for unit testing is a waste of time - although that didn't stop these devs. 100+ tests in the solution exercising all sorts of mock objects in the most bizarre and useless ways possible...

    But it's when I come to the actual implementation, and run through it end to end, that the true horror hits me. The code to generate the hash to send to the payment gateway is all present and correct; the code to check the hash being sent back from the gateway on notify doesn't exist.

    Yep, you read that correctly. When the gateway posts back a notification message, the code doesn't make any attempt to verify said message; it just assumes the contents are valid. Since the payment gateway API documentation is available to anyone, anyone with a bit of HTTP knowledge and a few guesses could easily craft their own notification message and send it back to the site. Oh look, now your purchase is free.

    The cherry on top (of the turd) is that this code was - allegedly - QA'd and signed off by one of our most senior developers, a guy who has been with the company over a decade and is now pushing to be promoted to a "software architect". While the juniors hold some blame for creating this mess, he's the guy who said it wasn't a mess.

    I fear he won't get his promotion.



  • @The_Assimilator said:

    Yep, you read that correctly. When the gateway posts back a notification message, the code doesn't make any attempt to verify said message; it just assumes the contents are valid.

    That's how checks work.



  •  Help me out if I'm missing something, but it sounds like the correct security is in place for communications that post the actual order info to the server, the problem is that the front-end doesn't validate the server's response.  This means a malicious 'hacker' could display their own messages "as though they are from the server", which might result in confused/irate customers if they are seeing bogus messages (like "everything is free!!!1"), however it cannot result in erroneous orders going through the system.  Yes?

     



  • @The_Assimilator said:

    I fear he won't get his promotion.
    Discarding this expectation would be better for your mental health than keeping it.



  • I think what is being said is that the payment provider issues a HTTP request to their server. It is then up to the server to validate that the HTTP request is indeed real and not a forgery.



  • Qualification: I know nothing about payment servers.

    But I think that the problem is the confirmation from the payment provider is supposed to confirm that the payment was made and that you should ship the product. I could buy a computer and enter "Code 12345, 12 Orchard Street, Cleveland Ohio" and that would be rejected by the payment provider and accepted by the seller and he would ship the  computer to that address and I would get a free computer. Yes?

     



  • @_leonardo_ said:

     Help me out if I'm missing something, but it sounds like the correct security is in place for communications that post the actual order info to the server, the problem is that the front-end doesn't validate the server's response.  This means a malicious 'hacker' could display their own messages "as though they are from the server", which might result in confused/irate customers if they are seeing bogus messages (like "everything is free!!!1"), however it cannot result in erroneous orders going through the system.  Yes?

     

    No. A MITM can intercept the message to payment operator, throw it to /dev/null and send a response pretending the payment was processed. And the system orders shipping the product because it believes the money were charged, but they were not.

    Sure, it requires a MITM or DNS poisoning, but still, unnecessary weakness.



  • @Ronald said:

    @The_Assimilator said:

    Yep, you read that correctly. When the gateway posts back a notification message, the code doesn't make any attempt to verify said message; it just assumes the contents are valid.

    That's how checks work.

     

    No, this is how cheques work. You can tell the difference like this: checks are checked and if a check doesn't check QA get sad, but cheques have no checks - we just hope the cheque checks out at the teller's desk.

     



  • @Bulb said:

    No. A MITM can intercept the message to payment operator, throw it to /dev/null and send a response pretending the payment was processed. And the system orders shipping the product because it believes the money were charged, but they were not.

    Sure, it requires a MITM or DNS poisoning, but still, unnecessary weakness.

    Or for the simpler minded, you could just make payment with an invalid/expired card which would be rejected by the payment processor, and since nothing checks the payment processors response, the site just assumes the order has been completed and marks it as paid.



  • @justanotheradmin said:

    @Bulb said:

    No. A MITM can intercept the message to payment operator, throw it to /dev/null and send a response pretending the payment was processed. And the system orders shipping the product because it believes the money were charged, but they were not.

    Sure, it requires a MITM or DNS poisoning, but still, unnecessary weakness.

    Or for the simpler minded, you could just make payment with an invalid/expired card which would be rejected by the payment processor, and since nothing checks the payment processors response, the site just assumes the order has been completed and marks it as paid.

     

     

    I don't think the expired card would work.  It sounds like it reads the response, but doesn't validate it.

     



  • @Mo6eB said:

    @Ronald said:

    @The_Assimilator said:

    Yep, you read that correctly. When the gateway posts back a notification message, the code doesn't make any attempt to verify said message; it just assumes the contents are valid.

    That's how checks work.

     

    No, this is how cheques work. You can tell the difference like this: checks are checked and if a check doesn't check QA get sad, but cheques have no checks - we just hope the cheque checks out at the teller's desk.

     

    Unless it's canceled.



  • @Ronald said:

    @Mo6eB said:
    @Ronald said:
    @The_Assimilator said:
    Yep, you read that correctly. When the gateway posts back a notification message, the code doesn't make any attempt to verify said message; it just assumes the contents are valid.

    That's how checks work.

    No, this is how cheques work. You can tell the difference like this: checks are checked and if a check doesn't check QA get sad, but cheques have no checks - we just hope the cheque checks out at the teller's desk.

     

    Unless it's canceled.
    There was a big scandal in the Prague school system. In order to boost graduation rates teachers were passing a lot of bad Czechs.

     



  • @El_Heffe said:

    @Ronald said:
    Unless it's canceled.
    There was a big scandal in the Prague school system. In order to boost graduation rates teachers were passing a lot of bad Czechs.

    I bought some out of date breakfast cereal the other day and since then I've been passing some bad Chex


  • Considered Harmful

    @RTapeLoadingError said:

    @El_Heffe said:
    @Ronald said:
    Unless it's canceled.
    There was a big scandal in the Prague school system. In order to boost graduation rates teachers were passing a lot of bad Czechs.

    I bought some out of date breakfast cereal the other day and since then I've been passing some bad Chex

    My friends are playing fantasy football, and there's a dispute over the number of interceptions thrown. They've been checking some bad passes.


  • @Bulb said:

    No. A MITM can intercept the message to payment operator, throw it to /dev/null and send a response pretending the payment was processed. And the system orders shipping the product because it believes the money were charged, but they were not.

    Sure, it requires a MITM or DNS poisoning, but still, unnecessary weakness.


    Whether that's difficult or not depends on the details. If the vendor doesn't want to handle credit card details at all (sensible option, because it avoids PCI compliance) then they construct the signed message and send it to the buyer's browser, which then passes it to the payment gateway's page so that the buyer submits the CC details directly to the gateway's server. In that setup the buyer is a MITM by design.



  • @Chame1eon said:

    It sounds like it reads the response, but doesn't validate it.

    I read that it was like PayPal's IPN: you provide a URL to PayPal and they will post to that when a payment happens. There's a method to verify that it is really PP posting and not some other party.



  • @The_Assimilator said:

    Oh look, now your purchase is free.

    Except that it isn't. Yes, up until the next administration run, maybe. But as soon as the company receives the payment and money from the payment provider, they should be able to see the discrepancy. Next step is verifying their shipment records with the payment records from the payment provider, and sue whoever abused this loophole for fraud.

    I mean, in theory you could get away with it if you worked through anonymous third parties who cannot be traced to you at all, but you're stealing and giving people an address. That's just never a smart move. Just because it is online, does not mean that forging payment information is somehow legal and okay. If this concerns small amounts, maybe the company will not go through all the legal hassle, but then we're talking the equivalent of walking into a grocery store and slipping an extra packet of chips under your coat. Sure, they can't see it during check-out so you get free chips, but don't delude yourself: you're a thief, taking the risk of getting caught.

    Don't get me wrong, I fully agree that the company should do this check, and that leaving it out is a potential problem (although it would greatly surprise me if it was actually being abused; a dutch food ordering company forgot the check on the forward-pass of their payment route which was much easier to abuse, and except for few students it was not abused for years). But rather than a catastrophic blunder, I would equate this sooner with "not locking the outside door in a restaurant bathroom": security flaw, potential for abuse, but if you can rely just a little bit on your customers being honest, not really a problem.



  • @FragFrog said:

    Except that it isn't. Yes, up until the next administration run, maybe. But as soon as the company receives the payment and money from the payment provider, they should be able to see the discrepancy. Next step is verifying their shipment records with the payment records from the payment provider, and sue whoever abused this loophole for fraud.

    I mean, in theory you could get away with it if you worked through anonymous third parties who cannot be traced to you at all, but you're stealing and giving people an address. That's just never a smart move. Just because it is online, does not mean that forging payment information is somehow legal and okay. If this concerns small amounts, maybe the company will not go through all the legal hassle, but then we're talking the equivalent of walking into a grocery store and slipping an extra packet of chips under your coat. Sure, they can't see it during check-out so you get free chips, but don't delude yourself: you're a thief, taking the risk of getting caught.

    And that's, I suspect, the reason why things like banks don't seem to take computer security seriously (nowhere near things like Gmail, facebook or WoW): they live in a different world, one where if you slip past security it's YOUR fault and you should be punished, instead of a world where if you slip past my security I'll thank you for telling me how you did it and immediately fix it.

  • Discourse touched me in a no-no place

    @FragFrog said:

    I mean, in theory you could get away with it if you worked through anonymous third parties who cannot be traced to you at all, but you're stealing and giving people an address.
    Give someone else's name and address, preferably someone you hate. Bonus points for ordering something for them that they really wouldn't want to admit purchasing in public.



  • @FragFrog said:

    Except that it isn't. Yes, up until the next administration run, maybe. But as soon as the company receives the payment and money from the payment provider, they should be able to see the discrepancy. Next step is verifying their shipment records with the payment records from the payment provider, and sue whoever abused this loophole for fraud.

    Let's say I go through the entire purchasing process, then before finalizing the transaction I instead change my mind and decide to not continue with the purchase. I cancel out of the payment provider's processing. As a simple end-user I can expect this would cancel the purchase at the website as well. However, the seller ends up shipping anyway and a few days later I find a package delivered to my doorstep.

    At this point that package contains unsolicited goods. Per my country of residence's laws – Sidenote: I think the laws in question stem from EU directives, which means similar laws exist across all member states of the EU. – I am not obliged to send unsolicited goods back to whoever sent them and I am also under no obligation to pay for them.
    Those goods are mine. Free. Legally. No fraud.


  • Considered Harmful

    @Ragnax said:

    @FragFrog said:
    Except that it isn't. Yes, up until the next administration run, maybe. But as soon as the company receives the payment and money from the payment provider, they should be able to see the discrepancy. Next step is verifying their shipment records with the payment records from the payment provider, and sue whoever abused this loophole for fraud.

    Let's say I go through the entire purchasing process, then before finalizing the transaction I instead change my mind and decide to not continue with the purchase. I cancel out of the payment provider's processing. As a simple end-user I can expect this would cancel the purchase at the website as well. However, the seller ends up shipping anyway I then proceed to send a falsified request to the original website indicating that the payment completed successfully, where it then fails to verify the digital signature and a few days later I find a package delivered to my doorstep.

    At this point that package contains unsolicited stolen goods. Per my country of residence's laws – Sidenote: I think the laws in question stem from EU directives, which means similar laws exist across all member states of the EU. – I am not obliged to send unsolicited goods back to whoever sent them and I am also under no obligation to pay for them.
    Those goods are mine. Free. IlLegally. No through fraud.


    FTFY



  • @FragFrog said:

    @The_Assimilator said:

    Oh look, now your purchase is free.

    Except that it isn't. Yes, up until the next administration run, maybe. But as soon as the company receives the payment and money from the payment provider, they should be able to see the discrepancy. Next step is verifying their shipment records with the payment records from the payment provider, and sue whoever abused this loophole for fraud.

    I mean, in theory you could get away with it if you worked through anonymous third parties who cannot be traced to you at all, but you're stealing and giving people an address. That's just never a smart move. Just because it is online, does not mean that forging payment information is somehow legal and okay. If this concerns small amounts, maybe the company will not go through all the legal hassle, but then we're talking the equivalent of walking into a grocery store and slipping an extra packet of chips under your coat. Sure, they can't see it during check-out so you get free chips, but don't delude yourself: you're a thief, taking the risk of getting caught.

    Don't get me wrong, I fully agree that the company should do this check, and that leaving it out is a potential problem (although it would greatly surprise me if it was actually being abused; a dutch food ordering company forgot the check on the forward-pass of their payment route which was much easier to abuse, and except for few students it was not abused for years). But rather than a catastrophic blunder, I would equate this sooner with "not locking the outside door in a restaurant bathroom": security flaw, potential for abuse, but if you can rely just a little bit on your customers being honest, not really a problem.

    This site is selling virtual services (memberships to be precise), so there's no need for a shipping address, just a credit card. And the amounts are small enough that suing wouldn't be viable, but enough that it would hurt. Additionally, the admin overhead of following up on fraudulent customers would quickly wipe out their bottom line. They need something bulletproof, not a leaky sieve.

    As for relying on customers to be honest... yeah. I sure hope you're never involved in implementing security of any kind.


  • Discourse touched me in a no-no place

    @The_Assimilator said:

    As for relying on customers to be honest... yeah. I sure hope you're never involved in implementing security of any kind.
    Yet if you never trust anyone at all, you'll totally fail to run a business or carry out virtually any job when working for someone else. (And yes, perfect security is only truly achieved when absolutely nothing becomes possible to ever change; nobody wants that.)



  • @dkf said:

    @The_Assimilator said:
    As for relying on customers to be honest... yeah. I sure hope you're never involved in implementing security of any kind.
    Yet if you never trust anyone at all, you'll totally fail to run a business or carry out virtually any job when working for someone else. (And yes, perfect security is only truly achieved when absolutely nothing becomes possible to ever change; nobody wants that.)

    @The Greatest American President* said:

    Trust, but verify

    * no it's not David Palmer


  • Discourse touched me in a no-no place

    @Ronald said:

    @The Greatest American President* said:
    Trust, but verify
    * no it's not David Palmer
    And log. The obsessive keeping of records is what makes retail banks relatively safe places to keep money; they might mislay it, but they will not actually lose it. (Does not apply to investment banking.)



  • @dkf said:

    @Ronald said:
    @The Greatest American President* said:
    Trust, but verify
    * no it's not David Palmer
    And log. The obsessive keeping of records is what makes retail banks relatively safe places to keep money; they might mislay it, but they will not actually lose it. (Does not apply to investment banking.)

    Yes, they are pretty good with records unless their low-cost contractors crash their systems for days at least three times, while the senior management is busy picking up individual cigarette butts called in by their mom or double-checking the colors on a car spray paint job in a remote branch.

    This is clearly better than using a buggy spreadsheet to manage risk.



  • @The_Assimilator said:

    The cherry on top (of the turd) is that this code was - allegedly - QA'd and signed off by one of our most senior developers, a guy who has been with the company over a decade and is now pushing to be promoted to a "software architect". While the juniors hold some blame for creating this mess, he's the guy who said it wasn't a mess.

    Sorry, but your "most senior developer" has been there for over 10 years? That's the first WTF. The second is that this person hasn't been promoted yet? That's strike 2.

    If you are working somewhere where a dev is still there as a dev after 10 years then there is a serious problem. He should have been promoted or fired a long long time ago.


Log in to reply