
In March, the WPScan WordPress security research team discovered Cross-Site Request Forgery (CSRF) protection bypasses in 37 WordPress plugins, affecting over 200,000+ active WordPress websites.
The vulnerabilities were responsibly disclosed, resulting in the 37 plugins either being patched or removed from the official WordPress plugin repository.
Cross-Site Request Forgery (CSRF) is a vulnerability that can allow an attacker to perform an action on your behalf. For example, if you visit a page on the web where the attacker has embedded their CSRF exploit code, and you are logged into your WordPress website, the attacker could perform actions such as adding testimonials, changing settings, injecting malicious JavaScript, and more, depending on where the vulnerability is.
When validating reported WordPress plugin vulnerabilities our team often comes across other vulnerabilities that affect the plugin. When our research team were validating a vulnerability discovered by one of our security researchers, we noticed that the root cause of the vulnerability was a mistake commonly implemented across many plugins in the official WordPress plugin repository.
The vulnerabilities were caused by the miss-use of the WordPress check_ajax_referer() function. The check_ajax_referer() WordPress function prevents Cross-Site Request Forgery (CSRF) attacks against WordPress AJAX requests. What is not very well known is if the function’s third parameter is set to false, then the PHP execution does not die. In most cases, this renders the check_ajax_referer() function useless and allows the CSRF request to be processed, even if the CSRF nonce is not valid.
Below is an example of a coding mistake that we reported in one of the plugins which lead to a CSRF bypass:
add_action( 'wp_ajax_some_action', 'some_ajax_callback' );
function some_ajax_callback() {
check_ajax_referer( 'ajax-nonce', 'security', false);
[...]
}
The safe code would remove false from the third parameter passed to the check_ajax_referer() function:
add_action( 'wp_ajax_some_action', 'some_ajax_callback' );
function some_ajax_callback() {
check_ajax_referer( 'ajax-nonce', 'security');
[...]
}
Or, if you really want to pass false to the third paramater of the check_ajax_referer() function, explicitly call the die() function as shown below:
add_action( 'wp_ajax_some_action', 'some_ajax_callback' );
function some_ajax_callback() {
if (!check_ajax_referer( 'ajax-nonce', 'security', false)) {
die('Wrong CSRF given');
}
[...]
}
This coding mistake was added to our WordPress Plugin Security Testing Cheat Sheet to help plugin developers and security testers discover security issues in WordPress plugins. And it will also be added to our How to Find WordPress Plugin Vulnerabilities ebook in a future release.
How to stay secure
Our customers that were using any of the affected plugins were warned about the vulnerabilities. If you have not yet installed our WordPress security plugin, get your free API token from wpscan.com to ensure your the first to know about security vulnerabilities affecting your WordPress website.