Server-Side Request Forgery (SSRF) Vulnerability in UpdraftCentral Dashboard
One way we help to improve the security of WordPress plugins, not just for customers of our service, but for everyone using them, is our proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. Through that, we caught a less serious vulnerability, a server-side request forgery (SSRF) vulnerability, being introduced in to the plugin UpdraftCentral Dashboard.
We now are also running all the plugins used by our customers through the same system used for the proactive monitoring on a weekly basis to provide additional protection for them.
The possibility of this vulnerability is also flagged by our Plugin Security Checker, so you can check plugins you use to see if they might have similar issues with that tool.
Server-Side Request Forgery (SSRF)
In the latest version of the plugin, a function, maybe_process_remote_asset_request(), was added to the file /site-management.php. That function runs whenever WordPress loads.
That function passes the value of the GET input “font” to the function readfile():
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | private function maybe_process_remote_asset_request() { if (!empty($_GET['udcentral_action']) && 'load_font' == $_GET['udcentral_action']) { if (!empty($_GET['font'])) { $font_url = urldecode($_GET['font']); $headers = get_headers($font_url, true); if ($headers && isset($headers['Content-Type'])) { header('Content-Type: '.$headers['Content-Type']); header('Content-Transfer-Encoding: Binary'); header('Content-disposition: attachment; filename="'.basename($font_url).'"'); readfile($font_url); exit; } } } } |
If there were no limit on what value can be passed, that would allow reading arbitrary files on the website, which would be a very serious issue. There is a restriction that limits the value to URLs due to passing the value through get_headers() and requires that the URL return a Content-Type header. That still allows requesting arbitrary URLs from the context of the server, which is server-side request forgery (SSRF).
As the code doesn’t appear to be utilized from the plugin, we can’t really assess what is supposed to be accomplished with that and how that would be properly secured. But at a minimum, a more appropriate function to make the request than readfile() would be wp_safe_remote_get().
WordPress Causes Full Disclosure
As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)
You can notify the developer of this issue on the forum as well.
After four years, the moderators have finally tacitly admitted they were behaving inappropriately and have made moves to fix the problems (though incompletely), so these full disclosures can be ended if they simply restore access to our accounts and plugins in the Plugin Directory. Hopefully that takes less than four years.
Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:
Proof of Concept
The following proof of concept will cause a request to our website’s homepage.
Make sure to replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/?udcentral_action=load_font&font=https://www.pluginvulnerabilities.com