On exploits and assessing security

Everything started on a summer Friday, August 19 2011, 23:23 BST (so it might be reported to Sat 20 Aug, depending on your timezone).
Kingcope, a Greek hacker known for a long stream of 0days and trash Greek music soundtracks, posts a very short email on the Full-Disclosure mailing list. The email has a promising title, Apache Killer, and an attachment: killapache.pl.

The script is extremely simple: 84 lines of perl, comments included, capable of killing any Apache web server.

The core of the attack is extremely simple: the script sends a (perfectly legit) request to the Apache server, including a Range header similar to this:

Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15,5-16,5-17,5-18,5-19, 5-20,5-21,5-22,5-23,5-24,5-25,5-26,5-27,5-28,5-29, -[..and many many more..].

What happens behind the scene is that Apache has to make separate copies of the response for each of those ranges and, guess what, it explodes.

The Range header (defined here in RFC 2616) has legitimate uses: for instance, PDF readers use it while you scroll down the page. Let us reiterate that the attack is a perfectly well formed request: "A byte range operation MAY specify a single range of bytes, or a set of ranges within a single entity."
On a side note, IIS only allows up to 5 ranges for each HTTP request, and it is not vulnerable - with the notable exception of IIS 5, but you don't have those around anymore, do you?

But back to our story. Apache reacted "quickly", issuing a security advisory [CVE-2011-3192] a mere 4 days after the release, on August 24 16:16 GMT [http://article.gmane.org/gmane.comp.apache.announce/58]. They acknowledged the bug, promising that "A full fix is expected in the next 48 hours.". Apache also provided a number of different mitigations, by using mod_rewrite, limiting the size of the request field or even a dedicated module.

+1 for having included so many mitigations inside the advisory, -1 for taking so long to give an official answer.

A number of different answers were surfacing by that time, including Spiderlab's suggestion of using ModSecurity (but truth be told the answer was already floating on some forums). The 24th was, in short, the moment where the general public started noticing the issue - also thanks to a The Register's article which, even though it drops a totally out of place comment on open source security, at least cites Zalewski.

And this is the interesting bit of the story: the bug was well known!
lcamtuf reported this exact issue in 2007 - just 4 years ago.

The reactions were, to say the least, wrong. William A. Rowe [of the Apache Software Foundation] answered: "With the host of real issues out there in terms of massively parallel DDoS infrastructures that abound, this is, as you say, quite a silly report.". Yeah, sure. The issue was also thought to be connected to the sliding window (Rowe: On the matter of your 1GB window (which is, again, the real issue), you have any examples of a kernel that permits that large a sliding window buffer by default).
Probably even lcamtuf did not understand the full impact of this issue - we are speaking about a full DOS against the default installation after all, even if it is very easily avoided - as he says: "William, again, this is not a critical issue; I did mention that, and if it were, I wouldn't report it that way". The issue was thus not really understood by both parties, or at least its full implications were not. If we go into the details of the bug report we must grant the fact that it focused more on the "network" attack vector - not exactly the one exploited by Kingcope's attack, which results in memory exhaustion. Siim Põder also tried to implement the attack, but failed. The thread then just died.

Bottom line: general failure of the community to identify and evaluate a risk in the absence of an exploit. So long for all the "risk assessment without full disclosure" talks: without an exploit, an entire community looking at the description of a bug in the most widespread web server of the world failed to evaluate risk.

At the same time, in the Apache dev@ mailing list there was not a single mention of the bug. Compare that to the mail thread [mod_deflate & range requests) from last August: http://mail-archives.apache.org/mod_mbox/httpd-dev/201108.mbox/browser, or here. This exploit, in the end, resulted in a ticket on the ietf with a request for changing the standards [http://trac.tools.ietf.org/wg/httpbis/trac/ticket/311]: that's what we call impact.

And all because an exploit was not developed in the first place...

MS Access SQL Injection Cheat Sheet Reloaded

SQL Injections are still very popular, for both ethical and unethical attackers.
Although numerous research covering this topic have been published, SQL Injection vulnerabilities in Microsoft Access powered websites didn't receive much attention.

Back in 2007, @_daath published the first MS Access SQL Injection Cheat Sheet. A few years later, NibbleSec decided to update the document in a brand new format. New stuff has been added as well as external resources have been merged.

Enjoy the reloaded MS Access SQL Injection Cheat Sheet

TYPO3-SA-2010-020, TYPO3-SA-2010-022 explained

On 16th December, TYP03 released a new security update (TYPO3-SA-2010-022) for their content management system. Apparently, this web-based framework is widely used in many important websites.
Within this update, TYPO3 team fixed a vulnerability that I've discovered a few weeks ago. In detail, this discovery pertains to a previous vulnerability fixed in TYPO3-SA-2010-020 and discovered by Gregor Kopf.

TYP03 decided to follow a policy of least disclosure. Although it's an Open Source project, no technical details are available in the wild besides these (1,2). As I strongly believe that this practice does not improve the overall security (as mentioned in a previous post), I've decided to briefly explain this interesting flaw.

From the advisory, we can actually deduce two important concepts:

A Remote File Disclosure vulnerability in the jumpUrl mechanism [..] Because of a non-typesafe comparison between the submitted and the calculated hash, it is possible [..]
In a nutshell, the JumpUrl mechanism allows to track access on web pages and provided files (e.g. /index.php?id=2&type=0&jumpurl=/etc/passwd&juSecure=1&locationData=2%3a&juHash=2b1928bfab)

The patch (see this shell script) simply replaces the two equal signs with three (loose vs strict comparisons).

That's the affected code:


Having this knowledge, it is probably clear to the reader that the overall goal is to bypass the comparison between $juHash and $calcJuHash. While the former is user supplied (string or array), the latter is derived from a substr(md5_value,10) (string).

In PHP, comparisons involving numerical strings result in unexpected behaviors (at least for me before studying this chapter).
If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically
If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.
For instance, the following comparisons are always TRUE:
if(0=="php")-> TRUE
if(12=="12php")-> TRUE
if(110=="110")-> TRUE
if(100=="10E1")-> TRUE
if(array()==NULL) -> TRUE
[..]
And again, also the following comparisons are TRUE:
If("0"=="0E19280311"){}
If("0"=="0E00106552"){}
If("0"=="0E81046233"){}
Consequently, we can pad and wait till the substring of an md5 hash resembles this form. If you do the math, you will discover that the combined probability of having such calculated hash is considerably less than pure bruteforcing.
~37037037 max trials (worth case) VS 3656158440062976 all possibilities
In practice, the number of iterations is even less as "0000E13131" and similar strings are also accepted.

To further improve this attack, I've discovered another bypass (TYPO3-SA-2010-022) which allows the disclosure of TYPO3_CONF_VARS['SYS']['encryptionKey']. In this way, it is possible to retrieve the key once and download multiple files without repeating the entire process. Using multiple requests, this attack takes a few minutes (8-20 minutes in a local network). A real coder can surely enhance it.

As you can see from the exploit (posted on The Exploit Database), the fileDenyPattern mechanism bypass is pretty trivial. A demonstration video is also available here (slow connection, sorry).

Keep your TYPO3 installation updated! A patch is already available from the vendor's site.

@_ikki