WordPress <= 2.8.3 Reset Admin Password Vulnerability

An exploit has been released for all current versions of WordPress including WordPress <= 2.8.3.

Laurent Gaffié who published the finding says:

An attacker could exploit this vulnerability to compromise the admin
account of any wordpress/wordpress-mu <= 2.8.3

From what I can tell the vulnerability allows an attacker to reset the admin user account without having a valid email address. This could certainly be used in a denial of service vulnerability, locking an admin out their site by continually changing the password.

You can change any admin password on any WordPress blog as follows (taken from exploit):

http://DOMAIN_NAME.TLD/wp-login.php?action=rp&key[]=

I’ve tested this and it does change the admin password, however, I haven’t looked at this for some time but I believe WordPress generates a fairly strong password after being reset, something an attacker would have difficulty brute forcing or guessing.

BlogSecurity has recommended before that the /wp-admin/* directory should be password protected or restricted to IP address. This would mitigate this problem. See our advisory here for details.

Random Posts

If you enjoyed this post, please leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

Quick fix: replace line 190 from wp-login.php with

if ( empty( $key ) || is_array( $key ) )

David!

I have tested this vulnerability in WP 2.0.11 and 2.6.2 and it didn’t work. You wrote that you tested it and saw that password was changed – in which WP version do you checked?

MustLive, thanks for the additional tests. I tested it on WP 2.8.3.

You shouldn’t really be using 2.0.x branch any more as its no longer maintained. Perhaps you could diff 2.6.2 and 2.8.3 wp-login files to see whats different.

[...] Bei der Version 2.8.4 handelt es sich ebenfalls um ein Sicherheitsupdate (für das es bereits einen Exploit gibt), so dass auch hier ein zeitnahes Update obligatorisch [...]

[...] Since morning I have been reading about latest password reset vulnerability found in wordpress  version <= 2.8.3. (Details) [...]

[...] WordPress <= 2.8.3 Reset Admin Password Vulnerability [...]

I’d say, if security is a priority, make sure you either know how the software you’re running works, or don’t use it at all. :)

Regards,
Zelest

> You shouldn’t really be using 2.0.x branch any more as its no longer maintained.
David, I’ve planed already to write a comment in your post about 2.0.x branch and I’d do it soon ;-).

Don’t worry I have never expected on WP guys and always tried to fix all holes by myself. I always exepect only on myself.

> Perhaps you could diff 2.6.2 and 2.8.3 wp-login files to see whats different.
I looked “on eye” sources of wp-login.php in 2.0.11, 2.6.2 and snippets from exploit and the idea of these files’ work is the same. In 2.6.2 and 2.8.3 these parts of code looks equal. The “if ( empty($key) )” line is the same in all these versions.

I have an assumption that it’s because of my PHP version and those PHP versions which you and Laurent Gaffié were tested. Maybe empty() in different PHP versions works differenly with arrays.

dt, nice and compact fix.

Jesper.

You are right. For example, I by myself make a lot of security checking in WordPress which I’m using (in all version which I used from 2.0.3 and higher). And I found many holes in WP, some of them I disclosed, some I’d do later.

But I did’n saw this issue in wp-login.php, because I thought that “if ( empty($key) )” is enough protection, but as Laurent showed it’s not (and it can be byppased by using of array). On the other hand, as I wrote before, in my version of PHP this code works fine and doesn’t allow to bypass this check. It’s possible that in older versions of PHP empty() works fine in such cases.

David, as you could hear, in WordPress 2.8.4 this hole was fixed.

Guys, about working this vulnerability in different PHP versions. As I tested just after I wrote previous comment, empty() works fine – the problem not in it. I tested work of empty() with arrays on my old PHP and it’s works fine, and also I checked this vulnerability on one of the latest PHP versions and empty() worked, but hole didn’t. So problem not in empty().

After I made additional research (in different WP versions), I found that attack not work at the second check – when picking out from DB to $user variable and checking it. The code in WP 2.8.3 and those older versions which I checked are similar, but hole doesn’t work. Also I checked on MySQL 4.x and 5.x, and the hole still didn’t work (i.e. there is no difference on various MySQL versions). So anyone can test it in different WP versions by himself to find vulnerable ones. So it’s strange why this hole doesn’t want to work in older versions of WP :).

Leave a comment

(required)

(required)