Tarsnap email confirmation bypassOver the past four years, Tarsnap's bug bounties have received quite a bit of attention. Most of it has been very useful — almost 400 mistakes (most either cosmetic or harmless, but some of them significant) have been reported and fixed — but it does also get some unwanted attention: Despite my clear statement that Tarsnap's bug bounties are for problems in tarsnap code, not for problems in the website, I regularly see people running automated vulnerability scanners... which invariably yield a selection of absurd non-vulnerability "vulnerabilities".
One consequence of these unsolicited security scans is that —
since they feed a variety of inputs to forms, including the account
creation form — I see a lot of obviously fake signup attempts
(alas, none yet from
the world's most obviously fake domain
name). These are harmless, since the signup code sends out a
confirmation email and the account isn't actually created until the
alleged registrant follows a link in that email; so I wasn't
concerned when I received an email last week telling me that someone
was trying to create an account as
Five minutes later, I was very concerned upon receiving an email
telling me that the registration for
had been confirmed and the account created.
This should not have happened, so I immediately started running down
a list of possibilities. Was it a forged email? No, the headers
showed it being delivered from the CGI script to the tarsnap web
server's qmail to the tarsnap mail server's qmail to my inbox. Was
a copy of the confirmation email — which should never have
gotten past the mail server — being misdelivered somehow? No,
the mail logs showed that the email to
went from CGI script to the web server's qmail to the mail server's
qmail and then was dropped. Was one of the CGI scripts on the tarsnap
web server compromised? There was nothing in the logs to suggest a
request of the sort which might have been used to exploit a bug; nor,
for that matter, anything to suggest that someone had been probing for
bugs, so if a CGI script had been exploited, it was done completely
blindly. Nevertheless, I disabled the CGI scripts just in case.
Had someone managed to compromise the web server or mail server? I saw no unexpected processes running; nothing abnormal in the logs; and neither server had rebooted recently (as might be required to install a kernel root kit). Of course you can't rely on anything from within a system to reliably diagnose whether it has been compromised, and I wasn't running auditdistd, so I couldn't be absolutely certain... but realistically, if an attacker was sophisticated enough to compromise either system without leaving any trace, how likely was it that they would blow their cover by creating an obviously impossible tarsnap account?
The mystery was solved a few minutes later when an email arrived from Elamaran Venkatraman: He hadn't compromised any servers or exploited any bugs in my C code; rather, he had found a dumb mistake in tarsnap's account-creation process.
For most people to create a Tarsnap account, only a few things are required: An email address, a password, and checkbox confirming that you agree to the Tarsnap legal boilerplate. You submit those to the Tarsnap server; it generates a registration cookie; it sends that cookie to you as part of a URL in the confirmation email; and when you click through that link and re-enter your password your account is created. So far so good — but some people need a bit more than that. Tarsnap is a Canadian company, and as such is required to remit sales tax for its Canadian-resident customers. Moreover, Tarsnap is required to issue invoices to its Canadian-resident customers — invoices which show the customers' physical mailing addresses — so if a registrant identifies themself as being a Canadian resident, they are taken to a second page to provide their name and mailing address.
But what of that confirmation email? Well, I didn't want someone who self-identified as a Canadian resident to create an account without providing the legally-mandated information, so I couldn't send out that email until they submitted the second page. On the other hand, they having provided their email address and password once already, I didn't want to ask for those again. And so, when I finally got all the paperwork sorted and started accepting Canadian customers in July 2012, I took the option which was simple, obvious and completely wrong: I passed the registration cookie as a hidden variable in the second-page form, to be echoed back to the server.
This of course is what Elamaran had found. To be clear, the registration cookie didn't reveal any server internals; the only thing it could be used for was to confirm an email address. But because it was being sent in the HTML response, anyone could "confirm" any email address, simply by claiming to be a Canadian resident and viewing the page source. Oops.
The fix for this was easy: Use two cookies, one for email confirmation and one for the Canadian-address-obtaining continuation. More importantly, I've moved the cookie-generation to where it belongs — within the routine which generates and sends the confirmation email — and I've added a comment to remind myself that the cookie must never be exposed via any channel other than an email destined for the address being confirmed.
That last part is ultimately the most important lesson from this: Comments matter! I don't know what I was thinking three years ago when I reused that cookie; but unless my memory was much better then than it is now, I almost certainly wasn't thinking about my original design from four years prior. While this was hardly a fatal bug — while I'll never know for certain, I doubt anyone exploited this email confirmation bypass, and the impact would not be severe even if someone did — it's an reminder of the importance of writing useful comments. I often see solo developers excuse a lack of comments in their code on the basis that they understand their code and nobody else will be touching it; this misses an essential point: I am not the same person as I was three years ago, nor do I understand everything I understood three years ago.
People make mistakes, and people edit code without fully understanding how and why it works. Leave breadcrumbs behind, even if you don't intend for anyone to follow you: When you try to retrace your steps, you might get lost without them.
Safe from what?I woke up this morning to a headline news story on CBC's website: Is your baby monitor safe? According to a literal reading of Betteridge's law of headlines, the answer to this question should be "no", although if you consider the spirit of the law — as a commentary on sensationalist journalism — then the answer should probably be "yes". To me, neither answer makes sense, because the question itself doesn't make sense.
What does it mean for a baby monitor to be safe? Some things are clearly essential: It should not explode; it should not release significant quantities of dangerous gasses; if it's designed to be placed within reach of a baby, it should not pose an electrocution or choking hazard. Less obviously, if it has data or power cables, those should be arranged to avoid effecting tripping hazards. On the other hand, it's far from clear if privacy is an essential component of "safety". Does it matter if someone within range of your wireless network can listen to your baby crying? Probably not — anyone that close to you has likely heard far more of your baby's crying than they want already. Similarly, unless you never leave home, video of your baby sleeping is readily available to anyone who passes you in the street.
The word "safe", like the word "secure", covers a wide range. Is a Tesla car safe? For most people driving through the streets of Vancouver, it's very safe. But if you're driving through a war zone, having a vehicle which is designed to protect you from bullets and shrapnel is probably more important than having a vehicle designed to protect you in a head-on collision. The answer to whether a vehicle — or a baby monitor — is safe isn't yes or no; it's another question: "Safe from what?"
I spent seven years as Security Officer for the FreeBSD operating system, and over the years I wrote somewhere around a hundred advisories for vulnerabilities in FreeBSD. We used a consistent format: Background, Problem Description, Impact, Workaround, Solution. Of these sections, the Impact was always the section I wrote most carefully, and the section I advised users to pay the most attention to; and it usually had a consistent format: "An attacker who..." (description of attacker, e.g., "has an account on a system", or "can connect to your wifi network") "can ..." (description of what the attacker can do, e.g., "gain superuser privileges", or "listen to your baby crying"). Both of those clauses were essential in order for users to decide whether they wanted to update their systems: If there are no attackers whom you're worried about (say, if all of your code runs as root and the vulnerability is limited to nonprivileged users), or you don't care about what attackers can do (say, if the issue limits them to listening to crying babies), then you don't need to worry.
Of course, if you're building a product or supplying a service, you should be concerned about any attacker and any outcome which your potential customers could plausibly be worried about; after all, you're (hopefully!) in a better position to understand the safety and security properties of your product or service than your customers are, but you don't know exactly what attackers or outcomes they will care about. For the online backup service I run, this means being concerned not just about random attackers around the internet, but also considering myself as a possible attacker (since I might be coerced, legally or otherwise); and considering not just disclosure of backups, but also disclosure of whether particular data has been backed up (I call this the RIAA attack: "Has anyone backed up this MP3 file?") and also tampering with backups (can someone change the passwords in your backups so that they can break into your server after you restore from those backups?) as attacks I need to worry about — not because I think everybody is going to be worried about such attacks, but because someone might be.
But if you're simply assessing a product for your own use rather than building a product for a wide audience, you should know what you're worried about and what you don't care about. So don't ask "is this baby monitor safe"; ask "will this baby monitor allow any attackers I'm worried about to do anything I care about".
And if you're writing headlines, please stop using vague terms like "safe" or "secure". The role of a headline isn't, no matter what tabloids might suggest, to convince people to read an article; the role of a headline is to help readers decide if they want to read the article, and imprecision serves no purpose there.