Our Security Review of WordPress Plugin Found Freemius Library Still Contained Vulnerabilities 3 Years After Major Security Incident
Three years ago, the Freemius library, which is a monetization library widely used in WordPress plugins, fixed a serious vulnerability only after a hacker had identified it and started exploiting it. The situation surrounding that was quite a mess. It would be reasonable to think that the developer of the library and the developer of the plugins, especially security plugins, using the library would have made sure to get the security of the library reviewed after that to address any other security issues, but that turns out not to be the case.
What makes that more striking is that the developer claimed after that went down that:
security is top priority for us
And that:
Even though we have a very strong security background, we conduct thorough code reviews and work with an experienced security researcher from the HackerOne community, yet this vulnerability still slipped through the cracks. ????
As part of our main service, we do security reviews of WordPress plugins selected by our customers. Earlier this month we did a review of a plugin with 100,000+ installs that contains the Freemius library. We found that the plugin and the Freemius library contained vulnerabilities and other security issues. It is hard to believe “thorough code reviews” could have been done of Fremius, as we did less than that and found multiple security vulnerabilities. The most serious vulnerability we found in Freemius is directly connected with the code that was the cause of the previously exploited vulnerability, but somehow wasn’t secured at the time.
The developer of the plugin promptly communicated with us and provided us with their fixes so that we could confirm the issues were addressed. By comparison, with the Freemius library, we only received an initial acknowledgement that the issues would be addressed, but nothing more.
Following the bad practices from three years ago the developer again has failed to make the fixed version of the library widely available, while a new version that partially addresses the issues we found has been released, it again isn’t available through the library’s GitJub project. With the latest update to that being put out on January 3.
Elsewhere though it is clear that the library has had security changes made, as for example, the plugin Featured Images in RSS for Mailchimp & More, which has 30,000+ installs, had this changelog for a new version released on late on Wednesday:
Updated Freemius SDK with improvements and security fixes, bump WP compatibility to v5.9.1.
The changes made are clearly based on the issues we notified Freemius of. Since this is now public, we can go ahead with detailing the issues.
While the vulnerabilities were addressed, some of the insecurity we found still hasn’t been addressed in Freemius.
Plugins With Over 5 Million Installs Impacted
Checking for usage of the Freemius library using a search of WP Directory indicates that over 800 plugins in WordPress’ plugin directory contain the library and that the 100 most popular of those have over 5.3 million installs. Among the most popular are five security realted plugins:
- WP Activity Log – 100,000 installs
- WP fail2ban – 70,000 installs
- WP Encryption – 50,000 installs
- SSL Zen – 30,000 installs
- Security Ninja – 9,000 installs
The two most popular of those, WP Activity Log and WP fail2ban, as well as SSL Zen, have yet to be updated to include the new version of Freemius
Authenticated Information Disclosure
What looks to be the most serious vulnerability we identified is that anyone logged in to WordPress has had access to the library’s debug log, despite it only being intended to be accessed by users with the Administrator role. The severity of that access would depend on if sensitive information got stored in the log.
What makes the lack of security on that stick out is that function being used, _get_debug_log, is registered two lines up from the function that was at the root of the exploited vulnerability, _set_db_option:
3430 3431 3432 3433 3434 | self::add_ajax_action_static( 'get_debug_log', array( 'Freemius', '_get_debug_log' ) ); self::add_ajax_action_static( 'get_db_option', array( 'Freemius', '_get_db_option' ) ); self::add_ajax_action_static( 'set_db_option', array( 'Freemius', '_set_db_option' ) ); |
That has been addressed by adding a capabilities check to the code (as well as a nonce check):
3575 3576 3577 3578 3579 3580 | static function _get_debug_log() { check_admin_referer( 'fs_get_debug_log' ); if ( ! is_super_admin() ) { return; } |
Cross-Site Request Forgery (CSRF)
The functionality that enables the library’s debug mode was also insecure, as it lacked protection against cross-site request forgery (CSRF). So an attacker could have previously caused a logged in Administrator to enable that without intending it.
That was addressed by adding a nonce check:
3522 3523 | static function _toggle_debug_mode() { check_admin_referer( 'fs_toggle_debug_mode' ); |
More Functionality Similarly Impacted
Both capabilities checks and nonces are basic security in a WordPress plugin, so their being missing in those locations is hard to square with the developer of the library’s security claims mentioned above.
Several other functions we notified the developer of also had capabilities checks and nonce checks added. Those were the function dismiss_notice_ajax_callback() in the file /includes/managers/class-fs-admin-notice-manager.php, as well as the functions _retry_connectivity_test() and _email_about_firewall_issue() in the file /includes/class-freemius.php.
Sanitizing and Validation Still Probably Lacking
Another issue that we noticed is that in a lot of places, the library is bringing in user input without sanitizing or validating it, which, if done, would improve security. A lot of that can be seen by looking at instance of usage of the function fs_request_get(), which brings in user input, in the code.
Unfortunately, the new version of the library only makes a change in that in regards to two of the functions previously mentioned in this post. Elsewhere, the code hasn’t been changed to address that.
Lack of Protection Against Direct Access to PHP Files
Most of the plugin’s .php files that didn’t appear to be intended to be directly accessed contained protection against direct access, but a few were missing that. We didn’t see anything that could be exploited in the files without the restriction in place, but restricting access to them would ensure that there isn’t any issue with that.
The issue was mostly addressed by adding the protection to all but one of the files missing it. The remaining file being /includes/fs-essential-functions.php.