Prajwal Tuladhar’s Blog
 
programming, life and some random thoughts

Archive for the 'security' Category

Aug 17 2009

WordPress remote admin reset password patch

Published by under security

The recent WordPress bug that could reset the admin password seems to have been updated in the new version of WordPress 2.8.4. Or if you are lazy like me, you can patch that bug yourself (I’m using quite old WordPress version).

What we need is filename called wp-login.php

Try to find the function called reset_password. If you are using version 2.8.3, then the line number should be 185. Here is the code for the function without any modification:


function reset_password($key) {
	global $wpdb;

	$key = preg_replace('/[^a-z0-9]/i', '', $key);

	if ( empty( $key ))
		return new WP_Error('invalid_key', __('Invalid key'));
	$user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s", $key));
	if ( empty( $user ) )
		return new WP_Error('invalid_key', __('Invalid key'));

	// Generate something random for a password...
	$new_pass = wp_generate_password();

	do_action('password_reset', $user, $new_pass);

	wp_set_password($new_pass, $user->ID);
	update_usermeta($user->ID, 'default_password_nag', true); //Set up the Password change nag.
	$message  = sprintf(__('Username: %s'), $user->user_login) . "\r\n";
	$message .= sprintf(__('Password: %s'), $new_pass) . "\r\n";
	$message .= site_url('wp-login.php', 'login') . "\r\n";

	$title = sprintf(__('[%s] Your new password'), get_option('blogname'));

	$title = apply_filters('password_reset_title', $title);
	$message = apply_filters('password_reset_message', $message, $new_pass);

	if ( $message && !wp_mail($user->user_email, $title, $message) )
		die('<p>' . __('The e-mail could not be sent.') . "<br />\n" . __('Possible reason: your host may have disabled the mail()function...') . '</p>');

	wp_password_change_notification($user);

	return true;
}

Just update the 2nd line of the function with:

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

for

if ( empty( $key ))

I know this is just a dead simple work around and upgrading to version 2.8.4 is the best option. One can expect more of these kinds of vulnerability in near future especially when using query string in default way (http://domain_name.tld/file.php?var1=value1&var2=value2).

Also have a look the way the above function is implemented in 2.8.4 and the bug is patched.

function reset_password($key, $login) {
	global $wpdb;

	$key = preg_replace('/[^a-z0-9]/i', '', $key);

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

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

	$user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s AND user_login = %s", $key, $login));
	if ( empty( $user ) )
		return new WP_Error('invalid_key', __('Invalid key'));

	// Generate something random for a password...
	$new_pass = wp_generate_password();

	do_action('password_reset', $user, $new_pass);

	wp_set_password($new_pass, $user->ID);
	update_usermeta($user->ID, 'default_password_nag', true); //Set up the Password change nag.
	$message  = sprintf(__('Username: %s'), $user->user_login) . "\r\n";
	$message .= sprintf(__('Password: %s'), $new_pass) . "\r\n";
	$message .= site_url('wp-login.php', 'login') . "\r\n";

	$title = sprintf(__('[%s] Your new password'), get_option('blogname'));

	$title = apply_filters('password_reset_title', $title);
	$message = apply_filters('password_reset_message', $message, $new_pass);

	if ( $message && !wp_mail($user->user_email, $title, $message) )
  		die('<p>' . __('The e-mail could not be sent.') . "<br />\n" . __('Possible reason: your host may have disabled the mail() function...') . '</p>');

	wp_password_change_notification($user);

	return true;
}

The exploit is the typical example of HTTP Parameter Pollution. If you haven’t gone thru the slide, I recommed you to have a look. The problem is that HPP can not be defended by using anti-XSS functions like htmlentities() and htmlspecialchars(). The way query strings are handled by the respective web servers like Apache, IIS and so on also makes it difficult to present universal solution. In my opinion, the best way to defend againsts HPP is to enable mod_rewrite and restricting the way key/value pairs are routed in a URL.


Comments Off

Aug 06 2009

HTTP Parameter Pollution – A new kind of attack

Published by under security

Okay, I definitely haven’t heard this term (HTTP Parameter Pollution) in the past. I came accross this post, and was quite amazed by the potential of this new breed of attack. It makes use of HTTP Query String by overriding the query key-value pairs. As we know that, this type of URL is perfectly valid:

http://domain.com?par1=value1&par1=value2

But the way, these type of query strings where a key has multiple values are interpreted in different way by respective environments. For example:

  • ASP.NET / ASP using IIS interprets the above query string as par1=value1,value2
  • PHP using Apache interprets the above query string as par1[0]=value1; par1[1]=value2

In order to get detail information about such attack, I strongly recommend you to view the slides:

Unusual behaviors are a usual source of security weaknesses.
Enjoy the slide!

Comments Off

RSS Feed
Subscribe by email
Follow me @ Twitter