The WordPress 404 to 301 plugin (100,000+ active installations), fixed a broken access control vulnerability affecting version 3.0.7 and below.
The plugin allows the administrator to manage 404 errors by creating individual redirections to other pages or websites. Due to a broken access control vulnerability, an authenticated user could view, create and edit redirections.
Broken Access Control
In the __construct
method of the “404-to-301/includes/admin/class-jj4t3-admin.php” script, the plugin registers the jj4t3_redirect_thickbox
and jj4t3_redirect_form
AJAX actions for authenticated users:
add_action( 'wp_ajax_jj4t3_redirect_thickbox', array( 'JJ4T3_Log_Listing', 'open_redirect' ), 100 ); add_action( 'wp_ajax_jj4t3_redirect_form', array( 'JJ4T3_Log_Listing', 'save_redirect' ) );
The open_redirect
function is used to view redirections and the save_redirect
function is used to edit them. They are both located in the “404-to-301/includes/admin/class-jj4t3-log-listing.php” script:
895 public static function open_redirect() { 896 897 // Yes, security check is a must when you alter something. 898 check_ajax_referer( 'jj4t3_redirect_nonce', 'nonce' ); 899 900 // Verify if the 404 value is found. 901 if ( empty( $_POST['url_404'] ) ) { 902 wp_die(); 903 } 904 905 $url_404 = $_POST['url_404']; ... ... 954 public static function save_redirect() { 955 956 // Yes, security check is a must when you alter something. 957 check_ajax_referer( 'jj4t3_redirect_nonce', 'jj4t3_redirect_nonce' ); 958 959 // Custom options for the 404 path. 960 $options = maybe_serialize( 961 array( 962 'redirect' => jj4t3_from_request( 'jj4t3_custom_redirect_redirect' ), 963 'log' => jj4t3_from_request( 'jj4t3_custom_redirect_log' ), 964 'alert' => jj4t3_from_request( 'jj4t3_custom_redirect_alert' ), 965 'type' => jj4t3_from_request( 'jj4t3_custom_redirect_type' ), 966 ) 967 ); ... ...
Both functions lack a capability check and rely only on the same security nonce lines 898 and 957. Nonces are used to protect against CSRF attacks but aren’t suitable for authentication or capability check because they could be compromised, e.g., they could leak in the HTML code.
The function used to populate and echo the nonce is get_redirect_content
, which too is loaded in the __construct
method:
add_action( 'admin_footer', array( 'JJ4T3_Log_Listing', 'get_redirect_content' ), 100 );
Because it is loaded by the admin_footer
hook, the security nonce (as well as the hidden form used to edit redirections) leaks in the backend section of WordPress, and thus can be viewed by a logged-in user in the source of every HTML page:
An authenticated user can retrieve the nonce and use it to interact with the two AJAX actions in order to view, edit or create redirections.
An attacker could exploit the vulnerability to redirect users to a malicious website, but also for spamming and, more interestingly, for phishing attacks:
Spamming:
Spammers could trigger 404 errors by visiting non-existent pages such as https://example.com/fakerolex
, create the redirection to their website and send the intermediary link in junk emails in order to hide the final site.
Phishing:
Attackers could create malicious links with one or more homoglyphs. For instance, in the following link, https://example.com/wp-аdmin/
, the а
character is not the ASCII a
(U+0061) but, instead, the Cyrillic а
(U+0430 or %D0%B0
). Accessing the link would therefore trigger a 404 error that will be logged by the plugin. The attacker could then create a redirection to another website and could try to trick an admin or any other user to click on the malicious link, in order to redirect them to another login page and attempt to steal their login credentials:
The redirection is performed via the Location
header:
$ wget -S http://example.com/wp-аdmin/ --2021-06-18 12:43:47-- http://example.com/wp-%D0%B0dmin/ Resolving example.com (example.com)... 127.0.0.1 Connecting to example.com (example.com)|127.0.0.1|:80... connected. HTTP request sent, awaiting response... HTTP/1.1 301 Moved Permanently Server: nginx/1.18.0 Date: Fri, 18 Jun 2021 05:43:47 GMT X-Redirect-By: WordPress Location: http://evil.com/wp-login.php
Recommendations
Update immediately if you have version 3.0.7 or below installed. If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this vulnerability.
Timeline
The vulnerability was reported to the authors on April 05, 2021, and a new version 3.0.8 was released on June 12, 2021.
Stay informed about the latest vulnerabilities
- Running WordPress? You can get email notifications about vulnerabilities in the plugins or themes installed on your blog.
- On Twitter: @nintechnet