Archive for the Uncategorized Category

Ferruh Mavituna has published a short paper called “Deep Blind SQL Injection” detailing a twist on the time-based side channel attacks. Instead of leaking one bit of information per request, the time delay is modified to carry more bits.

In the paper, he suggests multilpying the delay by some small factor (to reduce the chance for measurement error) and by the actual data we want to pass. If the factor is 2 seconds and we want to leak the number 10, the delay will be set to 20 seconds.

Another suggestion is to transfer 4 bits at a time, so in two queries one can get an actual byte of data. This is somewhat suboptimal for two reasons:
1. The usual entropy of data is much less than 8 bits per character
2. The channel may be able to carry more (or less) than 4 bits of data.

For example, if we had a reliable connection with the victim (so the factor can be reduced to 1 - 1.5 seconds) and we figure that causing delays of one minute per query are suitable (to maximise the transfer rate and minimize the chance of causing problems to the server, hence detection), we can aim to pass 40-60 bits with one query.

If, on the other hand the victim’s usual responses vary between 5 and 10 seconds (so our factor can’t be lower than 20 seconds) and the “comfortable” for the server delay is 30 seconds, we’re back to 1 - 1.5 bits per query.

In short, combining a simple compression with response measurements of the particular victim, we can potentially boost the transfer speed of the side channel even further.

The problem:
The user is expected to enter his email address in a form field.

The solution(s):

  1. Pass it through a simple check to see if it contains a @ sign.
  2. Pass it through a regexp checking for “name@domain.com” format.
  3. Pass it through a really complex regexp checking for full RFC 2822 correctness.
  4. Pass it through a really working really complex regexp checking for really full RFC 2822 correctness.
  5. Pass it through a really working really complex regexp checking for really full RFC 2822 correctness, and then you check if the domain in the domain part exists.
  6. Send a unique random token (in a link back to your site) to the email.

Email addresses can take really really complex forms, and still be RFC-valid. They can be RFC-valid, but the particular email provider may like only a subset of what the RFC requires (for example, for the local part - think “username” - of the email gmail allows only alphanumerics and dots, 6-30 characters). The domain name may not exist. It may exist, but not have an MX record (i.e. it will not accept mails). The domain may accept mails, but the local part may point to an non-existing account.

So what do we do? We use the last of the above options: we send a mail, and wait for proof that it’s readable by the user. But why don’t we do a validity check first? At least some sanity check? Okay, but keep it as a warning only: tell the user if the address doesn’t “look” valid, but don’t expect that your Really Correct Check ™ is actually correct, so don’t deny the form submission. Unless you’re okay with angry users / customers of course.

What if you want an email address that does not belong to the user (think e-cards). Well, then you sigh, pick one of the checking methods above except the last one, use it as a warning only (not as a fail test), and just send the mail and hope for the best.

Obviously, in both cases (whether the email is owned by the user or not), there is the problem that we’ll send a mail to a given email address without further questions. As we saw, we can’t really ask any meaningful question that will answer if the email is “valid”, besides sending an email, so we have a problem with spambots here. The solution is well known - deny access to the bots by protecting the form with a good strong CAPTCHA.

(Well, yes, it is, but it’s not correct to think so. Here’s why:)

What I will write about is applicable to all kinds of string injection (SQL injection, XSS, header injection, command line injection, etc.) vulnerabilities. Speaking in generalities (in order to encompass them all) will make the exposition much harder to read, so I will instead talk solely about SQL injection. The parallels with other “string injectables” rather than SQL queries (HTML pages, HTTP headers, etc.) are more or less straightforward.

An SQL injection attack happens (mostly) when malicious input breaks out of “value” context and leaks into the SQL “syntax” context. The most common example is when a quote is inserted and everything after the quote is interpreted as SQL statements. The offered remedy is to escape the values (among other things) so that all input will remain in the “value” context.

Here’s what the manual has to say (substitute “escape” for their “quote”) (emphasis mine).

Quote each non numeric user supplied value that is passed to the database with the database-specific string escape function.

Even ignoring that “non numeric”, the troubles start now:

What is “user supplied”? $_GET, $_POST, $_COOKIE, $_REQUEST are clearly user supplied. $_SERVER? Partly so. Database? It depends. (If you answered “no” to this one, go read about Second order SQL injection). Config vars? Nah, they’re fully in our control (hmmm)

First, let’s notice the lesser evil: time. After some of it, chances are that pieces of your code will get rewritten, patched or copy-pasted elsewhere. The assumption about the “user supplied”-ness of these values may change, and the risk of forgetting this assumption is great. (For an artificial example, imagine changing how a “default languge” setting could be redesigned - instead of being a site-wide config variable, it is now a per-user variable and kept in the database. Suddenly it becomes quite user-controllable)

The true “evil” is that we think about security, while we should have been thinking about the correctness of the code (”correct” in the sense of bug-free). Consider this: security holes are a subset of software bugs. If a piece of code is “bug free” (haha) it is also “secure”. And here comes the title: escaping is not a security measure! Escaping is a way to ensure that what we pass as “values” is indeed interpreted as a “value”.

Going back to the above questionary, imagine a config var containing a quote. It is not attacker-conrollable, so it’s not a security risk. It will still break any query it is inserted into withouth being escaped. All security holes are bugs, but not all bugs are security holes. All bugs should be fixed though.

The moral of all this long winded talk is this: don’t think of escaping as a security measure. Don’t think about “tainted” input and whether this $_SERVER index is user-controllable. Don’t “hide” assumptions in your code. Escape every value that goes in a query. This will fix not only the security holes, but also any possible data-related bug.

Hello, world! I decided to split the security content from my other blog here. I promise to keep the content in a more up-to-date timeframe than peasant latin.

Here are the security-related articles I’m too lazy to move:

CORE GRASP (potential) pitfalls
Moved: The Unexpected SQL Injection
Moved: The Curse of Magic Quotes

FireStats icon Powered by FireStats