PHP backdoor shells in Drupal: not always file-based

The other day I was trawling through the overnight OSSEC notifications received at a customer's infrastructure and I came across one such item:

OSSEC HIDS Notification.
2015 Jun 21 17:05:58

Received From: (XXXXXX.example.com) 11.22.33.44->/var/log/auth.log
Rule: 1002 fired (level 2) -> "Unknown problem somewhere in the system."
Portion of the log(s):

Jun 21 17:05:57 XXXXXX sudo: pam_unix(sudo:auth): conversation failed

--END OF NOTIFICATION

"That's odd", I thought. This server doesn't really get frequent logins let alone use of sudo.

I SSH'd into the server and ran 'last'. There were no recent logins at all - certainly none that coincided with that entry in the auth.log.

For good measure I checked /var/log/auth.log, and saw the immediate next entry:

Jun 21 17:05:57 XXXXXX sudo: pam_unix(sudo:auth): auth could not identify password for [www-data]

Uh-oh. Why would www-data, the user running the HTTP daemon/PHP, try and invoke sudo? That is really not normal.

A bit of investigation confirmed my fears. Despite this being a relatively new server at this company, their customer had uploaded a Drupal app that had never been patched against the SA-CORE-2014-005 SQL Injection vulnerability from October 2014, commonly referred to as 'Drupalgeddon'. The app had been uploaded many months after the vuln, but somehow escaped being patched by the organisation.

I have seen compromised Drupal sites before. A common lateral move by the attacker is to upload a PHP 'shell' backdoor. In 2012, I saw these uploaded as .php files into the sites/default/files/ area, which then provided the attacker with a nice interface with which to browse around the server and perform other tasks such as easily fetching further payloads of malware.

Ironically, Drupal was never meant to allow serving .php files from the sites/default/files area. My discovery (along with others who coincidentally discovered it at the same time) led to the Drupal core vulnerability regarding this .htaccess flaw, SA-CORE-2013-003.

Although this environment was not vulnerable to that file execution flaw, I checked for any uploaded shells anyway. I found nothing.

I did discover that a Drupalgeddon SQL injection had taken place, with the admin user compromised. What I then saw was kind of cute: the PHP core module had been enabled (or was already enabled), and an existing node was edited to replace its body content with a PHP shell's code.

The result was that visiting /node/2 showed this screen (the entry point to the shell UI):

This is interesting because virus scanners like ClamAV etc, which typically check the contents of files for viruses, could not pick this up. The shell exploit itself was stored inside the database.

It goes to show the importance of adequate intrusion detection. It also proved to me that my existing Drupalgeddon detection rule in OSSEC was not effective (it is hard to detect with log analysis since it can simply be a POST request that results in a HTTP 200 response). I got lucky that the attacker attempted to invoke sudo as www-data.

I would be interested to hear if anyone else has written IDS rules of any sort to detect a Drupalgeddon exploit.

Tags: