During the course of learning how to write a plugin, I realize it is very easy for a plugin to access information inside WordPress. A plugin has unrestricted access. Here is a quick demo about what can be done.
I was writing a plugin to intercept comments with hyperlinks. The actual content or function of that plugin doesn’t really matter. In my plugin, I can make a sql call to $wpdb which will give me wordpress admin’s password hash.
$results = $wpdb->get_results('select user_login, user_pass from wp_users where ID < 10;', OBJECT);
error_log("HACK: " . print_r($results));
It is an MD5 hash. With rainbow table or other techniques, the hash can be cracked in relatively short time. If the password is simple or a dictionary word, it will be cracked in no time.
Here is another one, which reads wp-config.php and gets the database credential.
$file = get_home_path() . '/wp-config.php';
$searchfor = 'DB_USER';
$contents = file_get_contents($file);
$pattern = preg_quote($searchfor, '/');
$pattern = "/^.*$pattern.*\$/m";
preg_match_all($pattern, $contents, $matches);
error_log("HACK " . implode("\n", $matches));
The problem is there isn’t a layer of access control in WordPress to grant / deny access from a plugin. Once installed, it has full access. We’d have to rely on wordpress.org to review the code.
These may be more extreme cases. There are other cases which are not as obvious. I’ve seen plugins wrongfully utilize the wp_options table to store session information. There were like 25 million records in the wp_options table. As wp_options fill up, the site becomes unbearably slow. Pull up the schema of that table, the option_value field is a longtext, which stores up to 4GB on MySQL. It doesn’t take a lot to saturate the innodb buffer. And because how wp_options is structured, it’s impossible to trace which plugin inserted junk.
Install plugins with extreme care and only if absolutely necessary.