IP Location Block is the only plugin which has an ability to prevent zero-day attack even if some of the plugins in a WordPress site have unveiled vulnerability. I call it “Zero-day Exploit Prevention for WordPress” (WP-ZEP).
In this article, I’ll explain its mechanism and also its limitations. Before that, I’ll mention the best practice of plugin actions.
Overview
There are three methods to prevent zero-day attacks. The first one is to inspect bad queries with the blacklisted signatures. And the second one is to filter out only the legitimate requests using the whitelist. Those methods are focused on the patterns of request.
The last one, which WP-ZEP adopts, is to close a hole of vulnerability in a certain way that is focused on the patterns of vulnerability.
A considerable number of vulnerable plugins and themes that were out there are lacking invalidating either the nonce and privilege or both. So WP-ZEP will make up both of them embedding a nonce into the link, form, and ajax request from jQuery on every admin screen.
What’s the best practice of plugin actions?
While we can find the answer at Stack Exchange, I’d like to describe it a little in detail.
Showing plugin page
An url to the plugin dashboard can be specified depending on its parent category as follows:
wp-admin/admin.php?page=my-plugin
wp-admin/tools.php?page=my-plugin
wp-admin/option-general.php?page=my-plugin
- …
Requesting to wp-admin/admin.php
On the plugin dashboard, we can provide an action do-my-action
via admin.php
with a form like this:
Or a link:
Requesting to wp-admin/admin-ajax.php
We can also do the same thing via admin-ajax.php
by GET
or POST
method using jQuery. This request can be handled by the wp_ajax_xxxx
action hook.
Requesting to wp-admin/admin-post.php
WordPress also gives us a chance to handle POST
request via admin-post.php
.
Processing the requests
All above-mentioned can be processed by the function my_action()
.
The mechanism of WP-ZEP
In my_action()
, the most important processes before doing my action are:
- validate user privilege with
current_user_can()
. - validate the nonce with
check_admin_referer()
. - validate the given input.
When a plugin developer loses one of those, the result becomes serious.
So WP-ZEP will make up 1. and 2. by embedding a nonce into the request.
The limitations of WP-ZEP
One big challenge for WP-ZEP is to embed a nonce. You already notice that there’re countlessly many ways to do their own job besides the best practice. For example, one can do the “job” without using “action”.
In this case, the requested “job” will be processed directly in their hander without any help from WordPress core. So WP-ZEP can do nothing about it.
Another big challenge is to decide whether the request handler is vulnerable or not it my_action()
is registered for both authorized and unauthorized users like this:
If WP-ZEP blocks the action do-my-action
, visitors on the public-facing pages can not get any services via the ajax call. So WP-ZEP should carefully identify the action only for the admin. If the action provides its services for both admin and visitors, all this plugin has to do is validating an IP address by its county code.
This causes a serious problem: vulnerability in Slider Revolution cannot be blocked when the attack comes from the permitted country. (Because it had added the above two actions 😠). To prevent this kind of attack, you should add the following snippet into your functions.php
to filter out the malicious signatures. (This functionality had already been implemented from version 0.2.2.0.)
The last limitation is related to the validation of user privilege. WP-ZEP can not know which privilege is needed to do-my-action
. For example, some plugins need manage_options
, while moderate_comments
is sufficient for others. So all WP-ZEP can do is to validate if a user is logged in or not as a minimum privilege.
This limitation will tolerate the vulnerability of Privilege Escalation. You should prohibit guest users from registrating to pretend it.
Conclusion
So many security plugins are there on WordPress.org, but nothing is perfect against the “Zero-day Attack”.
So I’d like to keep this plugin simple and light enough to collaborate with other plugins while playing a certain degree of role by itself 👻.