09 Nov

Properly Limiting Access to AJAX Accessible Functions Can Prevent Insecure Code from Being Exploited in WordPress Plugins

We recently introduced a tool for doing limited automated security checks of WordPress plugins. In putting that together we have tried to strike a balance between warning about enough possible issues to effectively identify real issues and trying to limit unnecessarily warning about things that are not real issues. That isn’t easy because most security vulnerabilities are not easy to spot, if they were, they likely would have been fixed by now and security wouldn’t be a big issue.

One of the areas we have decided to air on the side of warning of possible issues while knowing that plugins with perfectly secure code will be identified, is with plugin’s allowing functions to be accessed through AJAX to those logged in to WordPress as well as those not logged in. As a recent situation with the plugin Formidable Forms shows, allowing those not logged in to access those they don’t need to be able to access can introduce security issues that would not otherwise exist.

As we discussed in a previous post, a recently fixed vulnerability in that plugin has been used in attempts to exploit a vulnerability that was recently fixed in the plugin Shortcode Ultimate.

The vulnerability in Formidable Forms involved the ability to execute shortcodes through its function to preview a form. The preview is accessed through WordPress’ AJAX functionality and is registered to be accessed whether logged in or not:

add_action( 'wp_ajax_frm_forms_preview', 'FrmFormsController::preview' );
add_action( 'wp_ajax_nopriv_frm_forms_preview', 'FrmFormsController::preview' );

The line with nopriv registers it for those not logged in.

In looking over the code it looks like the plugin only provides links to preview a form to those logged in to WordPress, so it doesn’t look like access is needed for those not logged in. In that access had not been there, then the vulnerability wouldn’t have existed, as those logged in to WordPress are already allowed to execute shortcodes through AJAX.

In looking at the other AJAX registered functions in the plugin we found that there were four others that are accessible whether logged in or not. For one of those it is pretty clear that function isn’t intended to be accessed by those not logged in.

For the functions to export data from the plugin as a CSV or XML file the plugins makes the CSV function accessible whether logged in or not, while only making the XML function accessible to those logged in:

add_action( 'wp_ajax_frm_entries_csv', 'FrmXMLController::csv' );
add_action( 'wp_ajax_nopriv_frm_entries_csv', 'FrmXMLController::csv' );
add_action( 'wp_ajax_frm_export_xml', 'FrmXMLController::export_xml' );

In the CSV function the first thing done is to check if the request is coming from someone with proper permission:

public static function csv( $form_id = false, $search = '', $fid = '' ) {
	FrmAppHelper::permission_check( 'frm_view_entries' );

Seeing as that permission check ultimately involves using the current_user_can(), which would require that request comes from someone that is logged in for the check to pass, it doesn’t look like it is intended to be accessed by those not logged in.

So in this case you have a plugin with 200,000+ active installations where it looks like 40 percent of the AJAX functions registered to those logged in and logged out shouldn’t be that way and that one of those lead to a vulnerability being exploited in a plugin when otherwise wouldn’t have existed. That seems to be further confirmation that it makes sense to include this check in our tool.

We notified the developer of those seeming unnecessary AJAX registrations, but didn’t get any response in regards to that issue.

Leave a Reply

Your email address will not be published. Required fields are marked *