Moonpig is a British company that makes personalised crap.
If you want some cheap tat with a photo of someone's ugly baby on it, or if you thought
that sending someone a tacky and overly expensive card with their name printed on it is a good
gift, Moonpig was your place.
Except: yesterday, a developer called Paul Price disclosed a security hole which, according
to him, exposed all Moonpig users' personal details, to the level where you can reasonably
start to pull off identity theft.
So: how did it happen?
Well, first, here's how well-designed apps work.
You download the app, you log in with your username and password, they're checked on
the server over a secure connection, and if they're right the app gets given a token,
a random string of characters, like a browser cookie, that it can use in place of those
details in future.
That way, you're not storing the user's password anywhere on the device.
And if the app is built by a different company entirely, like you have a "Log in with Facebook"
button, or something like that, then there are extra precautions you can take so that
third-party app never even sees the user's password for a moment.
The most common one's called oAuth 2, you can look it up if you're interested.
Okay.
So: send username and password, get token, use token in future to prove you're authorised.
And that's what Moonpig did.
Except.
That token was always your customer ID.
Now on its own, that is bad, it means you have no way of revoking that app's permission,
ever, even if someone changes their password, it means that if someone finds out your customer
ID, they can impersonate you and there's nothing you can do but close your account, but it's
not truly catastrophic.
Because a well-designed customer IDs will be a long, randomly generated string, it'd
take thousands of years to guess someone else's...
...yeah, no.
Moonpig's customer IDs were consecutive.
If you were user 51624, them the person who signed up before you would be 51623.
And the person after you is 51625.
And remember, that's the only token that's being sent by that app -- or by any malicious
attacker pretending to be that app -- that customer ID number.
So you didn't need to guess anyone's username and password.
You didn't need to do any sort of cracking.
You could just send a request to Moonpig's server, attach someone else's easily-guessed
customer ID, and responses helpfully come back for them instead of you.
With that, you could get the name on someone else's credit card, you could get the last
four digits, you could get the expiry date, and their address.
That's been more than enough data, in the past, to call up Apple and get into an iCloud
account, at which point it's game over.
Nick their email address, nick their Amazon Web Services account if they've got one, run
up a ten-thousand-dollar bill mining Bitcoins on someone else's credit card.
And here's the crucial thing: because those ID numbers were sequential, a malicious attacker
could run through and grab the details of every single one of their customers.
There was no rate-limiting, no check to say "hey, that person's making a lot of requests
there, maybe we should shut them down for a bit".
It was a near-perfect storm of incompetent coding.
This isn't one line of code with a bug in it: these are decisions made by the site's
developers.
Don't get me wrong, I've written code this bad before, but it was years ago while I was
learning and I wasn't getting paid for it.
Now, credit to Paul Price for not only discovering this, but for responsibly disclosing it.
After finding the error, he kept quiet, he alerted Moonpig privately, gave them fair
warning, and only after they didn't solve it did he publish.
Now, he left it for a year, which is about eleven months more leeway than he reasonably
needed to give.
In that time, has someone malicious swiped the details of every customer and kept quiet
about it?
We have no idea.
Paul's report says he was also careful not to pull down details of any customer otherthan
himself, and the test users he set up to check the bug.
Remember, if you're playing about with things like this, there is a non-zero chance that
a company will try and sue you, or report you to the police, rather than solving the
security hole: there's a lot of risk and not all that much glory.
Now, I've found a couple of things like this in the past -- fortunately both times, the
companies in question solved them within 48 hours and said thank you.
There are two lessons here: one for developers, I'll get to that in a minute, and one for
the people non-technical who hire them.
If you're not technical, but you're listening to this and thinking "oh no, is our site vulnerable?"
Get someone to test it.
Even better, if you have the budget, hire someone outside your company to test it.
The search term you need is "pentest".
And when someone reports a security bug, get it fixed, say thank you, don't go into PR-spin
mode and ignore it.
On that note, I did ask Moonpig for comments this morning, and gave them the whole day
to reply: their PR company very quickly sent their press statement, which says: "We can
assure our customers that all password and payment information is and has always been
safe".
Now that is a suspiciously specific denial.
They didn't mention addresses, or impersonation, or anything else, or really any of the claims
at all.
I did ask about that, and if "payment information" included the last four digits of card numbers:
as I record this, seven hours later, they haven't replied.
They have, however, shut down the bit of their site that the app worked with.
If they do get back to me, I'll add it to the video description.
And developers: if you're making anything that stores private information, code like
you're being attacked.
Because you will be.
Never trust user input.
Assume that anyone sending anything to your site is malicious until proven otherwise and
prepare for the worst.
Don't think "ah, nobody'll ever notice this" -- they will.
Instead, think "how could I break this?".
Because I guarantee you, there will be someone out there who's thinking that too.