2009-08-12 33 views
14

Một lỗ hổng gần đây đã được tiết lộ ảnh hưởng đến WordPress 2.8.3 và cho phép người dùng quản trị bị khóa tài khoản của họ bằng cách thay đổi mật khẩu.Hiểu rõ về lỗ hổng Wordpress

This post tiết lộ đầy đủ chi tiết về lỗ hổng và bao gồm các đoạn mã có liên quan. Bài đăng đề cập rằng 'Bạn có thể lạm dụng chức năng đặt lại mật khẩu và bỏ qua bước đầu tiên và sau đó đặt lại mật khẩu quản trị bằng cách gửi một mảng tới biến $ key.'

Tôi muốn được một người quen thuộc với PHP giải thích lỗi chi tiết hơn.

Những người bị ảnh hưởng nên update đến bản phát hành 2.8.4 mới có vẻ như sửa lỗi này.

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

Cảm ơn bạn đã vô tình cảnh báo tôi cập nhật lượt cài đặt từ của tôi. :-) –

Trả lời

17

Vì vậy, $ key là một mảng trong chuỗi truy vấn với một đơn trống string [ '']

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

reset_password được gọi với một mảng, và sau đó preg_replace được gọi :

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

preg_replace chấp nhận eithe r một chuỗi hoặc một chuỗi các chuỗi. Nó regex thay thế không có gì và trả về cùng một mảng. $ Key là không có sản phẩm nào (đó là một mảng của một chuỗi rỗng) để điều này xảy ra:

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

Bây giờ từ đây, tôi cần phải đi đọc nguồn wordpress cho cách chuẩn bị cư xử ...

More :

Vì vậy, chuẩn bị các cuộc gọi vsprintf trong đó sản xuất một chuỗi rỗng

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

Vì vậy, SQL là:

SELECT * FROM $ wpdb-> người dùng ĐÂU user_activation_key = ''

nào sẽ rõ ràng trận đấu sử dụng admin (và tất cả người dùng mà không cần activation_keys tôi giả sử).

Và đó là cách thực hiện.

+0

một mảng trống sẽ trả lại giá trị true cho một kiểm tra rỗng(), nhưng bằng cách truyền phím [] = bạn nhận được một mảng với một chuỗi rỗng làm phần tử duy nhất của nó. vpsprintf() trả về một giá trị, thay vì xuất một giá trị để mã mẫu của bạn không thực sự nói bất cứ điều gì. Trong cả hai trường hợp, lý do của bạn là âm thanh và kết quả cuối cùng là như nhau. – Greg

+0

Đã thêm các chỉnh sửa của bạn –

+0

Cảm ơn bạn đã phân tích! – PaulG

Các vấn đề liên quan