2009-08-12 21 views
14

Se ha divulgado recientemente una vulnerabilidad que afecta a WordPress 2.8.3 y permite que el usuario administrador se bloquee de su cuenta al cambiar la contraseña.Comprender la vulnerabilidad de Wordpress

This post en Divulgación completa detalla el defecto e incluye fragmentos de código relevantes. La publicación menciona que 'Puede abusar de la función de restablecimiento de contraseña y omitir el primer paso y luego restablecer la contraseña de administrador enviando una matriz a la variable $ key.'

Me gustaría que alguien familiarizado con PHP explique el error con más detalle.

Los afectados deben update a una nueva versión 2.8.4 que aparentemente corrige la falla.

wp-login.php: 
...[snip].... 
line 186: 
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')); 
...[snip].... 
line 276: 
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login'; 
$errors = new WP_Error(); 

if (isset($_GET['key'])) 
    $action = 'resetpass'; 

// validate action so as to default to the login screen 
if (!in_array($action, array('logout', 'lostpassword', 'retrievepassword', 
'resetpass', 'rp', 'register', 'login')) && false === 
has_filter('login_form_' . $action)) 
    $action = 'login'; 
...[snip].... 

line 370: 

break; 

case 'resetpass' : 
case 'rp' : 
    $errors = reset_password($_GET['key']); 

    if (! is_wp_error($errors)) { 
     wp_redirect('wp-login.php?checkemail=newpass'); 
     exit(); 
    } 

    wp_redirect('wp-login.php?action=lostpassword&error=invalidkey'); 
    exit(); 

break; 
...[snip ]... 
+1

Gracias por avisarme accidentalmente para actualizar las instalaciones de my word press. :-) –

Respuesta

17

Así $ clave es una matriz en la cadena de consulta con una cadena vacía sola [ '']

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

reset_password se llama con una matriz, y luego preg_replace es llamado :

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

porque preg_replace acepta eithe r una cadena o una matriz de cadenas. Regex no reemplaza nada y devuelve la misma matriz. $ clave no está vacío (que es una matriz de una cadena vacía) así que esto sucede:

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

Ahora de aquí, tengo que ir a leer la fuente de wordpress para saber cómo se comporta preparar ...

Más :

Así se preparan las llamadas vsprintf que produce una cadena vacía

$a = array(''); 
$b = array($a); 
vsprintf("%s", $b); 
//Does not produce anything 

Así que el SQL es:

SELECT * FROM $ wpdb-> usuarios DONDE user_activation_key = ''

Qué hará parecer partido del usuario administrador (y todos los usuarios sin activation_keys supongo).

Y así es como.

+0

una matriz vacía devolverá true para una comprobación empty(), pero pasando la clave [] = obtendrá una matriz con una cadena vacía como único elemento. vpsprintf() devuelve un valor, en lugar de generar uno, por lo que el código de muestra realmente no dice nada. En ambos casos, su razonamiento es sólido y el resultado final es el mismo. – Greg

+0

Agregó sus correcciones –

+0

¡Gracias por su análisis! – PaulG