None of this is new its just me trying to understand it. This vulnerability only resets the admin password, which is then emailed to the admin. Someone could potentially DOS the admin with a small script to continually reset the password but overall this is just an annoyance. This is mainly due to a lack of input validation on the $key variable. How this seems to work is WordPress is using a black list method to check to see if the key is empty and it also has no checks to see if the key is empty before the query is ran.

Proof of Concept:

Why does it reset admin?

When $key is passed an array[] it is treated an empty string. This will in turn match every user within the database. The first user just happens to be the admin, which WordPress will reset.

$user = $wpdb->get_row(
"SELECT * FROM $wpdb->users
WHERE user_activation_key = %s", $key));

The Issue.
It looks like empty() will treat an array as an empty string and not return an error.

if ( empty( $key ) )
return new WP_Error('invalid_key', __('Invalid key'));

The Fix.
WordPress has released a fix which is shown below. This is still a black list approach and only adds an extra check for the array.

if ( empty( $key ) || is_array( $key ) )
return new WP_Error('invalid_key', __('Invalid key'));

This is still using a black list method and I also think some improvements can be made before the query statement. I believe some blame can be put on PHP by not throwing an exception to an empty array. When time permits I would like to play around with other things that could be passed to $key. I’m still exploring other possibilities of this not just being a password reset that is sent to the admin. If anyone has some ideas, I would love to hear.

References: Read More →