The recent situation with plugin Display Widgets was yet another reminder that there are serious problems with the management of the WordPress Plugin Directory. Unfortunately one of the many of problems is that people behind it and others on the WordPress side of things seem to have no willingness to have an open conversation about the problems, which could lead to things being improved. Instead they shutdown conversations, as they did with one going on about this situation with this plugin and as they have in the past. That means that not only are mistakes not being learned from, but improvements that could limit future situations from happening are unlikely to be done.
While the people on the WordPress side of things don’t seem to be all that interested in fixing things, we are continuing to looks at ways we can do things to pick up the slack. Back in June we introduced a new feature to our service where we try to proactively catch serious security vulnerabilities as changes are made to plugins in the Plugin Directory (with more customers we could expand this to less serious vulnerabilities). Since we became aware of the situation with Display Widgets we have been looking if we could incorporate anything from that situation in to the monitoring. Through that we have noticed what seems to be us something that should probably be changed with Plugin Directory’s handling of obfuscated code. Unfortunately as we mentioned in the previous paragraph there doesn’t seem to be a willingness to even entertain that how things are done is in need of improvement, so we will share that here.
Part of how the malicious code in Display Widgets worked was by getting data from another website. In a comment on one of the posts we wrote the situation, it was suggested that the Plugin Directory should be searched to see if other plugins referenced a domain name being used by this plugin.
In a reply we noted two issues with that, the first being that multiple domain names had been used. A more advanced search could be used to check if other domains being used in plugins are on the same IP address (which would be a likely indication that they controlled by the same person). The second issue we noted was that in what was then the latest version of the plugin, the domain name had now been obfuscated, so either type of search wouldn’t work.
Obfuscating that would seem to be in violation of the Plugin Directory’s guidelines:
4. Keep your code (mostly) human readable.
Intentionally obscuring code by hiding it with techniques or systems similar to
p,a,c,k,e,r‘s obfuscate feature, uglify’s mangle, or unclear naming conventions such as
$z12sdf813d, is not permitted in the directory. Unfortunately, many people use such methods to try and hide malicious code, such as backdoors or tracking. In addition, WordPress code is intended for anyone to be able to learn from, edit, and adapt. Making code non-human readable forces future developers to face an unnecessary hurdle. Minified code may be used, however the unminified versions should be included whenever possible. We recommend following WordPress Core Coding Standards.
In Display Widgets the obfuscation was done using the following base64 encoding:
$endpoint = base64_decode( $_update ? ‘aHR0cDovL3N0b3BzcGFtLmlvL2FwaS91cGRhdGUvP3VybD0’ : ‘aHR0cDovL3N0b3BzcGFtLmlvL2FwaS9jaGVjay8/dXJsPQ==’ );
In the comments of an article on the situation at the WordPress Tavern there was reply from a member from the Plugin Directory team to a query about disallowing base64 encoding in the directory. They wrote:
Any use of Base 64 in plugins actually sends me an email when committed. I read all of those emails and look at the code. 99% of them are totally harmless and reasonable. I’ve continued to read them all for the last 5 years because of that 1% that’s not.
Depending on what it is they are reviewing it would seem difficult to believe that they could effectively review it all. Below are the instances of some base64 keywords in just the changes made to plugins in the Plugin Directory last Thursday:
- base64: 3409
- base64_encode: 350
- base64_decode: 202
We have been doing some testing to see if it would make sense to incorporate a search pattern based on the how base64_decode() was used to obfuscate the address in Display Widgets into the proactive monitoring of changes made to plugins to identify serious vulnerabilities. With a search pattern based on that there were a more manageable 19 results for the changes made to plugins last Thursday.
What is Being Obfuscated
In looking over those results we found that a variety of items are being obfuscated in plugin code. Some of them are as follows.
There was an email address:
$cabGridTestMessage="Cab Grid on $cabGridProSite is testing compatibility for Cab Grid Pro. cURL returned $cabGridCurlResponse";$m=base64_decode("bWFpbC50ZXN0QGNhYmdyaWQuY29t");
There was an OAuth 2.0 client ID:
$oauth2_id = base64_decode('aXA3NGR2Zm1sOHFteTA5');
There were examples of SQL code used in SQL injection in the text of a security plugin:
$sDescription = sprintf( _wpsf__( 'This will block sql in application parameters (e.g. %s, etc).' ), base64_decode( 'dW5pb24gc2VsZWN0LCBjb25jYXQoLCAvKiovLCAuLik=' ) );
All of those examples seem like they might be reasonable to be obfuscated. The email address being the most obvious of those. But some of the other entries seem more problematic.
In one plugin there is obfuscation of an address of a remote server being connected to using two different functions for making that type of connection:
$response = wp_remote_get( base64_decode( 'aHR0cHM6Ly9zYWxlc3dvbmRlci5iaXova2xpY2t0aXAtY2FwaS9jaGVja19saWNlbnNlLnBocA==' ) . '?' . $datastring, array( 'timeout' => 30, 'httpversion' => '1.1' ) );
$ch = curl_init(base64_decode('aHR0cHM6Ly9zYWxlc3dvbmRlci5iaXova2xpY2t0aXAtY2FwaS9jaGVja19saWNlbnNlLnBocA=='));
We have a much harder time believing that is justifiable.
The obfuscation of the address has been done in that plugin for over a year plugin.
Through monitoring we do of indications of vulnerabilities being fixed, we came across another instance of obfuscation being used with another function for making remote connections, which was added in a new version of a plugin on Thursday and labeled as “Security update”:
In addition to not being able to search for other usage of domain names when the addresses are obfuscated like that, if someone was trying to track down what is causing outbound connections from their website, searching the files would also come up empty when the address is obfuscated.
While trying to catch all instances of address being obfuscated would be difficult, it would be quite easy to catch all of three of the instances shown above. Seeing as base64 encoded are claimed to being checked by someone involved with Plugin Directory, they would seem be aware and okay with what is going on.
If someone reading this is aware of some reason why addresses need to be obfuscated like they are in the code above we would love to hear about in the comments, because we haven’t been able to think of one so far.