Another 0day in UserPro — Remote file upload / Stealing WordPress admin access / UserPro Privilege Escalation

Another 0day in UserPro — Remote file upload / Stealing WordPress admin access / UserPro Privilege Escalation

January 16, 2014 8:53 am 4 comments

So, after I’ve pointed out that UserPro has file upload vulnerability, DeluxeThemes (developer of UserPro) deleted my comment and updated their plugin..

This should fix the vulnerability and clients can have a good night’s sleep, right?

..

..

nonono

it is still possible to upload other kinds of files (e.g. php5 or php4 works on some servers)

REMEMBER, USING WHITE LIST IS FAR MORE SECURE THAN USING BLACK LIST

But the fun isn’t over..I have checked other parts of the code as well, and I’m not surprised that there are other vulnerabilities too
It’s convenient to use AJAX, but it’s easy to overlook the vulnerabilities when using it
userpro/functions/ajax.php :

add_action('wp_ajax_userpro_save_userdata', 'userpro_save_userdata');
function userpro_save_userdata(){
	global $userpro;
	extract($_POST);
	$output = '';
	$userpro->set($field, $value, $user_id);
}

and the $userpro->set function is defined in userpro/functions/api.php

function set($field, $value, $user_id){
	update_user_meta($user_id, $field, esc_attr($value) );
}

you can POST almost any wp_usermeta key along with its value and user_id to wp-admin/admin-ajax.php?userpro_save_userdata and it will get updated..

That’s not all..Also, check out this part of code in userpro/functions/ajax.php:
 

add_action('wp_ajax_userpro_process_form', 'userpro_process_form');
function userpro_process_form(){
	global $userpro;
	extract($_POST);
	foreach($_POST as $key=>$val) {
			$key = explode('-',$key);
			$key = $key[0];
			$form[$key] = $val;
	} extract($form);
	/* form action */
	switch($template) {
	...
	case 'edit':
	userpro_update_user_profile( $user_id, $form );
	...
	}
}

 
and this part in userpro/functions/user-functions.php
 

function userpro_update_user_profile($user_id, $form) {
	foreach($form as $key => $form_value) {
		if ( isset($key) && in_array($key, array('user_url', 'display_name', 'role', 'user_login', 'user_pass', 'user_pass_confirm', 'user_email')) ) {
			/* Save passwords */
			if ($key == 'user_pass') {
				if (!empty($form_value)) {
					wp_update_user( array ( 'ID' => $user_id, $key => $form_value ) ) ;
				}
			} else {
				wp_update_user( array ( 'ID' => $user_id, $key => $form_value ) ) ;
			}
			if (isset($key) && !strstr($key, 'pass')){
				update_user_meta( $user_id, $key, $form_value );
			} else {
				delete_user_meta( $user_id, $key );
			}
		}
	}
}

This function takes $_POST array, turns it into $form array stripping the dash from the variable (so template-1 becomes template), and then uses this array to update the wp_usermeta AND wp_user…such fail..
It is also possible to change password using other templates from userpro_process_form, but that’ll do

By the way, to get this plugin for free you can download the demo version, and do this change in functions/api.php (haven’t tested,but pretty sure it will work).

function verify_purchase($code, $api_key=null, $username=null, $item_id=null) {
	if (!$api_key) $api_key = userpro_get_option('envato_api');
	if (!$username) $username = userpro_get_option('envato_username');
	$Envato = new Envato_marketplaces();
	$Envato->set_api_key( $api_key );
	$verify = $Envato->verify_purchase( $username , $code); 
	if ($item_id != '') {
		if ( isset($verify->buyer) && $verify->item_id == $item_id )
			return true;
		return false;
	} else {
		if ( isset($verify->buyer) )
			return true;
		return false;
	}
}

to

function verify_purchase($code, $api_key=null, $username=null, $item_id=null) {
	return true;
}

Preview

P.S. just got a message from UserPro relating to the vulnerabilities, and it said just 4 words — “fuck off upme slave” (upme is a plugin from previous post), now I’m even more surprised how such blatant ignorant guy got 700 sales

Leave a reply


%d bloggers like this: