It Seems Like the Security Review of New WordPress Plugins Should Have Caught This CSRF/XSS Vulnerability in LeaderBoard LITE
As part of our proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities we manually look at a lot of code that doesn’t end up leading to the vulnerability that is being flagged as possibly being caused by the automated portion of that, but sometimes, as is the case of LeaderBoard LITE (LeaderBoard Plugin), we find another vulnerability in the same block of code as where the possible vulnerability was flagged. That is a brand new plugin that was supposed to go through a security review before being allowed in the Plugin Directory. The situation could actually be worse, if not for some of the insecure code in the plugin being broken.
In the plugin, what was flagged was this line which handles a file upload:
86 | move_uploaded_file($_FILES["upload"]["tmp_name"], $file_path_new); |
The extension of the file to be uploaded is limited to .sql, so there wouldn’t be an arbitrary file upload vulnerability, which is what is of most concern with that type of code:
71 | $allowedExts = array("sql"); |
76 | if (($_FILES["upload"]["size"] < 2000000) && in_array($extension, $allowedExts)) { |
There still could have been a vulnerability since the code that is part of is intended to make arbitrary changes to the database of the website by applying changes that are included in the file being uploaded, but the code looks broken as a request is sent to the page /wp-content/plugins/leaderboard-lite/admin/pages/update.php, which errors out when accessed directly. That isn’t a great sign for the security of the code in the plugin based on what we have recently been seeing in regards to the poor state of the code in plugins that have vulnerabilities that are widely exploited.
Looking at the code slightly above all of that in the file /admin/pages/settings.php, there is more insecure code. First the POST input variable is passed through extract(), which is something our Plugin Security Checker tool was updated to warn about recently after we noticed vulnerabilities caused by that:
36 | extract($_POST); |
We have long offered the team running the Plugin Directory free access to the advanced mode of that tool for free.
Right after that there is code to determine if the plugin’s settings should be updated and there is no check for a valid nonce, so there looked to be the possibility of a cross-site request forgery (CSRF) vulnerability:
38 | if ($save_settings== 'Save Settings') { |
The easiest way to confirm that there is that type of vulnerability is in a web browser, since you can easily see if in fact no nonce is sent or if a valid one is every checked for (by modifying it, if it exists). That also can be easily used to see if there is a related cross-site scripting (XSS) issue with the settings.
We did that and confirmed there is a cross-site request forgery (CSRF)/cross-site scripting (XSS) vulnerability and that seems like a security review should check for, due both the ease of doing that and that these types of issue have been part of the cause of widely exploited vulnerabilities in popular WordPress plugins.
Here is a snippet of the code showing that there is no sanitization done when saving the settings:
49 | $options["stripe_secret"] = $stripe_secret; |
68 | update_option('LeaderBoardSettings', $options); |
And here is code showing a lack of escaping:
9 | $options = get_option('LeaderBoardSettings'); |
245 | <input type="text" name="stripe_secret" value="<?php echo $options["stripe_secret"]; ?>" id="stripe_secret" class="log-in-input" /> |
Those combined lead to cross-site scripting (XSS).
Where this could get worse is if someone could change the plugin’s setting when they are not logged in as an Administrator, but in this case access to the code is limited to those users.
Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since multiple previously full disclosed vulnerabilities were quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.
Proof of Concept
The following proof of concept will cause an alert box with any available cookies to be shown when visiting the plugin’s setting page, /wp-admin/admin.php?page=lbd_settings, when logged in as an Administrator.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin.php?page=lbd_settings" method="POST"> <input type="hidden" name="save_settings" value="Save Settings" /> <input type="hidden" name="stripe_secret" value='"><script>alert(document.cookie);</script>' /> <input type="submit" value="Submit" /> </form> </body> </html>
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.