Hacker News new | past | comments | ask | show | jobs | submit login

Also, if there is any sort of timing difference on valid/invalid card numbers. Boom... timing attack / CC oracle :)



Checked and the Mastercard one someone posted below doesn't seem to be vulnerable to this. My real card number and a dummy mastercard number with valid prefix and check digit both returned a 200 OK in around 1.01s. A random 16digit number without valid check digit returned 400 Bad Request in about 800ms. Decided to check that one since they have a completely useless machine-readable catchpa.

For Visa it was 835ms for valid, 762ms for dummy, prefix and check digit appears to be checked client side.


100ms is /massive/ for a timing delta but you really need a lot of samples. I have exploited timing deltas that were not much more than a handful of machine code instructions in terms of execution time. But you really do need a lot of samples to confirm small deltas. It starts getting impractical for many APIs (someone will notice, hopefully).


> someone will notice, hopefully

Or more likely "someone will notice, eventually"


This comment is why I love hackernews


See: https://rdist.root.org/2010/07/19/exploiting-remote-timing-a... and Crosby 2007. I got into infosec around 06 and tptacek, Nate Lawson and some others were my heroes. Now I run my own consulting firm with a bunch of cool people :)

Also in infosec: what is old is new. We still find shitty comparison routines (timing attacks) and SQL injection... some day :)


I just found a use-case for the sleep( rand(1000) ) function :-)


Nope!

If the rand function produces uniform random numbers, then with enough samples the signal comes out ontop the noise.

If it is non-uniform, then with enough samples you can determine the non uniformity, and you are at square 1 again.

Use proper security instead of obscurity.


Easily accommodated for. I can get the execution run-time and store in an average in memory for some time-period and have the sleep function top-up the difference between the two paths. Not sure what the "proper security" method is to prevent execution deltas.


Why not just run the thing (which takes some small fraction of time), then pad to five seconds, and respond. Since your work will be done in milliseconds, padding to nearest five seconds will remove any noise.

And it's not a thing anyone has a legitimate interest in submitting more than that per second.


Adding five seconds to everything just adds five seconds, it doesn't matter if the difference between the two requests is .01s or 5.01s.


The parent said "pad to 5 seconds" not "add 5 seconds". Thus everything would be 5 seconds (never 5.01). The difference between a hit and a miss would be exactly 0s. Note that I'm not advocating for or against this solution; rather, clarifying the conversation.


Pad to, not pad by.

I.e. the padding to add is (5 - duration_of_operation) with duration of operation being far lower than 5 s.


Depends. With comparison functions you can implement a constant time comparison that takes the same amount of time. In this case it isn’t really a crypto problem, so anything where we are confident about things taking the same amount of time is fine. Basically in some parent method/func make sure we always spend 2000ms or whatever time is that is always greater than the max runtime of the slowest path. Secondary / defense in depth mitigations would be rate limiting this page and making it purposefully slow on response, just to make it that much harder to collect samples / abuse it without being noticed. The captcha is a nice touch, but it didn’t seem particularly strong (a good captcha solver could break it). Still, captcha will chase off a lot of script kiddies. You don’t have to be faster than the bear, just faster than the slowest person ;)


rand() produces linear distributon, which is uniform. Do I understand properly that rand() + rand() would return normal distribution, so #2, for which you can determine the non uniformity?

What would be a proper first step to harden API for timing attacks?


Adding any random noise, even perfect randomness, doesn't prevent the attack. It just means the attacker needs more samples.


rand() + rand() does not produce normal, but adding together a few thousand rands does start to approach it. Central limit theorem.


rand() + rand() does not give normal. If there is any statistical difference between the timings, it's in theory possible to break.

An easy mitigation would be to just drop the card number into a queue and process asynchronously without waiting and returning to the user.


Flood the queue with invalid numbers and timings can still be worked out.


I would have gone for `sleep(1000)` and have it run in parallel with the actual function, so that every request takes 1000 milliseconds


I'd expect any submissions to this are just appended to a database without any actual validation beyond the trivial Luhn checksum and then there's a batch process once a day (maybe the same one that actually generates whatever marketing "insights" they claim to provide) that reads from there and ignores any card numbers from the opt-out DB.


You would hope that. I’ve been in infosec doing application security as a consultant a long time. Developers have often destroyed my hopes :)


> You would hope that. I’ve been in infosec doing application security as a consultant a long time. Developers have often destroyed my hopes :)

I used to work at a big bank in the US and the parent's description sounds exactly like how it would work.


You could be right but I have found almost this exact bug in production systems (credit card oracle sitting on the public Internet of a big card processor with no rate limiting and a really obvious timing delta). Both scenarios (batch or live processing) are pretty likely IMO. Just depends on what mess of APIs you happen to end up on.


Government and banks have been continuously using computers since the 60s, so as a result there’s a lot of “fancy web API to collect data… that gets batch processed by an ETL on a mainframe overnight.” Much more of it than I realized as a young dev at least.


Huh... create script to fill DB with all possible Visa numbers, tomorrow's "marketing insight" will suddenly be an empty file because everything will be excluded.

Bonus, if they can't separate which exclusions were from legitimate requests and which came from this script, they can't just delete those entries from the database.

Of course, no one should do this...


> Bonus, if they can't separate which exclusions were from legitimate requests and which came from this script, they can't just delete those entries from the database.

I think they would probably just declare them all invalid, and roll back to yesterday.


I think that millions of requests from a particular IP address might give the game away.


Perfect use case for Splunk.


Coming from the industry - MC & Visa typically don't know if exact card is valid or not. They admit range of numbers to an issuer (bank, revolut-type, whatever), and issuers system is queried for each transaction - card can be created at any time without notifying card schemes.

There's some exceptions (tokens etc.), but not relevant to this use case.


There's already Luhn and a list of valid starting digits...


Yes, which aids the spamming.

The first 6 digits of a card number is called the BIN code. That leaves just 9 digits that have to be spammed.

The fact that BIN lists are publicly available is reducing the space significantly.


I think the parent meant "card number that actually is in use and works" when saying "valid", not "follows the rules of card numbers".


Card number alone doesn't get you anywhere.

An expiration date will get you a bit farther, but you really need the CVV also.


Which would give you worthless information




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: