I have never done any Wordpress development and have no experience at all with the technical architecture of Wordpress. I am self hosting a Wordpress instance and am investigating a recent attack on my instance where the attacker was able to reset the password of my admin account.
Once thing that I noticed was that I have the Post SMTP plugin installed, and that plugin seems to keep a log of all outgoing e-mails. As an admin, I can view the outgoing password reset e-mails including the password reset link, so if an attacker somehow got access to the e-mail log, this would explain how they managed to change my password.
I had a look at how Post SMTP loads an e-mail in the admin UI. It makes a requests to admin_ajax.php
like so (ajaxurl
is /wp-admin/admin-ajax.php
):
var logsDTSecirity = jQuery( '#ps-email-log-nonce' ).val();
jQuery.ajax( {
url: ajaxurl,
type: 'POST',
data: {
action: 'ps-view-log',
security: logsDTSecirity,
id: id,
type: toDo
},
success: function( response ) {
...
}
} )
The nonce is created in the plugin using the following code:
<input type="hidden" id="ps-email-log-nonce" value="<?php echo wp_create_nonce( 'security' ) ?>" />
On the server side, the function view_log_ajax()
of the Post SMTP plugin serves the mail. It is registered like this:
$email_logs = new PostmanEmailLogs;
add_action( 'wp_ajax_ps-view-log', array( $email_logs, 'view_log_ajax' ) )
I cannot find anything that looks like an access control in the view_log_ajax()
function, apart from the verification of the nonce:
if( !wp_verify_nonce( $_POST['security'], 'security' ) ) {
return;
}
It seems that the admin_ajax.php
script can be called by all users. As a regular user without any rights, when I change the admin colour scheme for my user profile, it also calls that script.
According to wp_create_nonce
, the nonce is a simple hash based on the session cookie, the user ID, the current time stamp and the “action” (which in this case is security
), so it should be simply to create a valid nonce on the client side.
With all this, I have a suspicion that the e-mail log can be reached by everyone. However, when I try to replicate the call to admin_ajax.php
, I get a 400 Bad Request, even when I comment out the nonce verification on the server. My question is: Does admin_ajax.php
have any particular security measures in place? What is producing the 400 Bad Request? Do you have any tips how I could investigate the issue further?