Invented a Security Feature and Is Very Proud of It!

Author:  Follow: TwitterFacebook
Job Title:Sarcastic Architect
Hobbies:Thinking Aloud, Arguing with Managers, Annoying HRs,
Calling a Spade a Spade, Keeping Tongue in Cheek

Today’s rant will be about the developers who’re inventing features (more specifically – security features), and are so proud of them that these features get deployed without discussion and without understanding the implications. This lack of discussion and comprehension, in turn, often leads to disasters.

Throwing the key away as a security feature

Many of us have experienced problems which are related to overzealous developers pushing security features without taking enough time to think them through. In many cases, the reason behind the problems we’re experiencing is so deeply hidden that we cannot actually attribute it. However, in my experience I’ve seen several cases when it was obvious that the problem is a result of a security (mis)feature; moreover, once I was able to observe the investigation for reasons behind the problem, which has resulted in a successful identification of the culprit. So, we’ll start our discussion with a few real-world examples of those security misfeatures to get an idea how these things can hurt, and will proceed with an analysis of how these situations can be avoided before they become painful and embarrassing.

Strike 1: Spam Filter which Filters Out Replies to Own Mail

Once upon a time, there was a webmail provider, let’s name it X (it wasn’t the largest one, but they’ve got quite a few million users, which wasn’t something to sneeze at, at the time). And they attached their own ads at the bottom of e-mails they sent (you’ve seen this kind of stuff for sure). And everything was good, until they’ve deployed a significant “improvement” to their spam filter, which (as most of heuristic-based spam filters out there) aimed to filter out outright ads.

Hare with omg face:As a result, most of the replies were put into a 'Spam' folderYou can guess what happened then – when somebody@X sent an e-mail to the outside world, the ad by X got attached to the e-mail. When someone else (@some-other-provider) replied, the original e-mail (including the ad) was by default copied into the reply. When this reply reached X, it was treated as spam because of the ad in it (despite the fact that this very ad was appended by X itself). As a result, most of the replies (like 80-90% of them) were put into a ‘Spam’ folder by X.

This problem persisted for quite a few days, and it took X quite a long time to get rid of it. It caused a very big and very public backlash, causing quite a few customers to move their mailboxes from X.

Strike One.

Strike 2: Credit Card Processors and Obsession with Chargebacks

Chargeback Chargeback... is the reversal of a prior outbound transfer of funds from a consumer's... credit card.— Wikipedia —Within the credit card industry, there is one Big Scary Monster which every merchant is really afraid of: it is the so-called chargeback. When you got your credit card statement, and you found something-which-you-didnt-pay-for on it, you can complain to your bank (known as “issuing bank”) and your bank initiates the process of “chargeback” with the “merchant’s bank”. In short, if the merchant cannot provide some kind of proof that it did provide a service – your complaint is considered in your favour, and you get your money back (if you wonder why merchants are not all bankrupt given this system, I shall tell you I’m wondering about it myself since I’ve learned about chargeback mechanics; however improbable it sounds, it seems that most people out there are way too honest to abuse this system).

The really bad thing for a merchant when the chargeback happens is not even because they’re losing money on it. What can be worse than that is an additional (and very steep) fine which merchant needs to pay to the bank if the merchant is over a certain percentage of chargebacks (such as 1%, which isn’t exactly much).

So, it is understandable that merchants (and especially Internet merchants, which need to process cards in “without card present” mode, and this is inherently more risky) are really, really afraid of the chargeback monster.

Hare wondering if you are crazy:One thing nobody realised for a while is that the system with the least possible amount of chargebacks is the system which rejects all transactions outrightAs a result, back in 90’s, during early days of the credit card processing over the Internet, all the merchants and processors were obviously obsessed with chargebacks. To address their concerns, all kinds of security measures were implemented, with an obvious result that for most merchants, getting paid for their goods became more and more difficult. However, in the name of War on Chargebacks (any parallels with War on Terrorism and War on Drugs being, of course, purely accidental and unintended), nobody cared about this reduction in incoming payment flow due to security system being overzealous, and whichever protection system could claim the lower chargeback number won the merchants’ and processors’ hearts and money. One thing nobody realised for a while is that the system with the least possible amount of chargebacks is the system which rejects all transactions outright; the market of protection systems was moving full-speed to this bright zero-chargeback future (at the cost of no transactions going through), when somebody somewhere realized that Something Really Important (namely money for the merchants) was missing in the picture of this bright future.

Turing Test The Turing test is a test of a machine's ability to exhibit intelligent behavior equivalent to, or indistinguishable from, that of a human— Wikipedia —It was (very roughly) around 2005, when the industry started to realize that it is not only chargebacks which count, but also payment rejection rate. In most cases, it is much better to have fraud prevention system which allows 0.1% of chargebacks to go through while having 1% rejection rate, than another fraud prevention system which has chargebacks at only 0.01% at the cost of having 10% rejection rate.

The finding above was a real shock to the payment industry, and has caused quite a few operational changes, including much less overzealous automated order rejection (passing questionable orders to manual review instead), and  much more frequent use of manual (and therefore expensive!) techniques such as manual order reviews and attempts to contact the customer to find out if the order is legitimate. As a side note, we might suspect that this move to manual processing from automated one may indicate that payment fraud is a one good Turing test, but this point is pretty much beyond the scope of this article.

BIN Card issuers refer to the leading six digits1 on the card as an ‘issuer identification number (IIN)’, or ‘bank identification number (BIN)’— Wikipedia —Still, even now there are quite a few merchants out there (especially in Europe) which ask me to fill 20-field forms, with all the irrelevant stuff such as place where I work(!). After I’ve finished a Herculean task of filling all these fields, they feed it to their supposedly “Really Smart Fraud Detection System”, which, after thoroughly ignoring most of these fields, rejects my order because my IP address and BIN of my credit card don’t belong to the same city.  Needless to say that once it happens, I don’t visit that merchant anymore, preferring Amazon whenever possible. As Amazon has never used those way too overzealous fraud detection mechanisms (they do have an automated fraud prevention, but it doesn’t have this kind of security misfeatures and has an extremely low false positive rate), and it is a very clear market leader who’s light years ahead of the competition – maybe this will eventually convince the other merchants that not all fraud protections are created equal. If this will not convince them – customers will go to the merchants with fewer security misfeatures (read: Amazon).

Strike Two.

1 Wikipedia is a bit wrong here: in practice, BIN i.e. prefix which identifies the bank, can be anywhere from 4 to 10 digits, though the idea is still the same; however, databases with BIN information are classified so I cannot blame Wikipedia for this mistake.


Strike 3: Protection from Credit Card Expiration Going Backwards

Once upon a time, I’ve seen how those security misfeatures are introduced in practice, and it was quite an interesting experience. At that time, I worked for a company which needed to process credit card payments via a payment processor. So far so good, and it worked reasonably well. Then, on one rather gloomy day, the manager stormed the developers’ office and asked: “WTF have you changed in the system? Rejection rate went up more than three-fold!” Luckily enough, we didn’t deploy anything on the day before, so we had quite a good alibi, and investigation has whizzed by us without the prosecuting manager deciding to charge any of us with a crime against The Company.

Surprised hare:There was a guy in the payment processor company, who invented and implemented a new security feature. Moreover, the guy was very proud of his invention.Long story short: it was a guy in the payment processor company, who invented and implemented a new security feature, and deployed it on the exactly that day. Moreover, the guy was (as we were told) very proud of his invention.

His idea was based on an observation that credit cards are never re-issued with the expiration date being earlier than a previous expiration date for the same credit card number. So (he thought), if we see a transaction for the same card which we have already seen, and with an expiration date which is earlier than an expiration date which we have on file for the same card – then something is obviously wrong, and he can reject the transaction outright, without going to the bank (and going to the bank costs their processor some money even if the transaction is to be rejected, so there was a good reason for him to avoid going to the bank – that is, if the transaction was doomed to be rejected).

So, he had a really good reason to implement this change; however, there was one teensy problem with his reasoning (and with his implementation). He forgot to mention that this check (and automated rejection) makes sense only if the previous transaction was approved, and rejected the new transaction even if the previous transaction was rejected, i.e. his (erroneous) pseudo-code was along the lines of:

prev_trans = find_last_transaction_by_pan(request.cc_pan);
  //PAN is a fancy name of the credit card number
assert(prev.trans == NULL || prev_trans.cc_pan == request.cc_pan);
if(prev_trans != NULL &&
  prev_trans.cc_expiry_date > request.cc_expiry_date) //CANNOT GO BACK IN TIME
    return REJECTED;
//further processing with going to the bank etc.

The problem with this implementation was that if the user mistyped her expiry date (for example, typed “11/16” instead of the correct “10/16”), and then got to the processor, and got rejected, she wasn’t able to make a transaction with a correct “10/16” expiration date with this processor, ever2, because the code above would reject the transaction outright. So those users have tried, and tried, and tried, and got rejected, rejected, and rejected.

The fix would be simple:

prev_trans = find_last_transaction_by_pan(request.cc_pan);
assert(prev.trans == NULL || prev_trans.cc_pan == request.cc_pan);
if(prev_trans != NULL &&
  prev_trans.status == APPROVED &&
  prev_trans.cc_expiry_date > request.cc_expiry_date) //CANNOT GO BACK IN TIME
    return REJECTED;
//further processing with going to the bank etc.

but as far as I know, the guy was expressly prohibited from fixing it (our manager has made quite a lot of noise about money and customer goodwill he lost), and it was simply rolled back to the pre-security feature state.

Strike Three, Security Misfeatures Are Out!

2 ok, at least until she got her card re-issued


Lessons to be Learned

While those stories may be funny to read (especially to those not involved in cleaning up the mess afterwards), I need to justify reading this site to your bosses, so every article needs to have some kind of moral in it. Ok, here comes the moral of the story.

The problems described above, including the last one, were quite embarrassing to many people involved, so let’s think what these guys could have done to avoid it. For the sake of being more specific, let’s concentrate on the last case and on the guy who has wrote the “protection from going backwards” security misfeature.

BA, a.k.a. Business Analyst is someone who analyzes an organization or business domain and documents its... processes or systems, assessing... its integration with technology.— Wikipedia —So, what he could do about it? Testing? As far as we know, he did test this feature, but as it has failed only in one very specific scenario, testing didn’t reveal the problem (and more testing wasn’t likely to reveal it either, at least without using previous data, see below). In general, security features is one field where failures and bugs are very likely to slip past testing. Still, is there something we can do to avoid his painful experience?

Actually, there are several things which you should do in this regard:

  • don’t allow your natural excitement about your invention to carry you away. Stay calm, and be ready to accept criticism.
  • discuss the feature with BAs (if any), or with a manager (which he did, but not in sufficient details)
  • discuss the feature internally with fellow team members (which he didn’t)
  • discuss the feature with merchants, including us (with us having a chance to note this scenario, or at least knowing that the change is coming and looking for the impact)
  • avoid being too proud of your invented feature, until it has been shown to work properly. Inventing garbage is easy, inventing something useful is much more difficult.
Don't like this post? Comment↯ below. You do?! Please share: ...on LinkedIn...on Reddit...on Twitter...on Facebook


Cartoons by Sergey GordeevIRL from Gordeev Animation Graphics, Prague.

Join our mailing list:


  1. says

    Another great article. This was very entertaining, as mistake stories always are. And yes, I do think this can be justified to my boss. Learning is hard work.

    Also, what was with the grumpy bunny on the logo yesterday? Almost got away with it.

  2. Marcin says

    Sorry for nitpicking, but “assert(prev_trans.cc_pan == request.cc_pan);” right above a test for NULL seems like… no one turned asserts on when testing the solution.

    Otherwise, wow…

    • "No Bugs" Hare says

      As Garfield the Cat has said once: “We have a technical word for it. We name it ‘OOOPS!” ;-). Thanks, fixed now (I hope).

Leave a Reply

Your email address will not be published. Required fields are marked *