2009-08-12 113 views
14

最近發現一個漏洞影響WordPress 2.8.3,並允許通過更改密碼將admin用戶鎖定在其帳戶外。瞭解Wordpress漏洞

This post關於Full Disclosure詳細說明了這個漏洞,並且包含了相關的代碼片段。該帖子提到'您可以濫用密碼重置功能,並跳過第一步,然後通過將數組提交給$ key變量來重置管理員密碼。'

我會對熟悉PHP的人感興趣,更詳細地解釋錯誤。

那些受影響的應該update到一個新的2.8.4版本,這顯然修復了這個缺陷。

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

謝謝你不小心提醒我更新我的文字按安裝。 :-) – 2009-08-12 19:17:42

回答

17

所以$關鍵是在查詢字符串的陣列與單個空字符串[ '']

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

reset_password被調用與陣列,然後preg_replace函數被調用:

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

因爲preg_replace接受eithe r一個字符串或一個字符串數組。它的正則表達式不會替換,並返回相同的數組。 $關鍵不是空的(這是一個空字符串數組),所以出現這種情況:

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

現在從這裏,我需要去閱讀如何準備的行爲WordPress的源...

更多:

所以準備調用vsprintf產生一個空字符串

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

所以SQL是:

SELECT * FROM $ wpdb->用戶WHERE user_activation_key = ''

哪樣顯然匹配的管理員用戶(和不activation_keys所有的用戶我想)。

就是這樣。

+0

一個空數組將返回true爲空()檢查,但通過傳遞key [] =你得到一個空字符串作爲其唯一元素的數組。vpsprintf()返回一個值,而不是輸出一個,所以你的示例代碼並沒有真正告訴任何事情。在這兩種情況下,你的推理是合理的,最終結果是一樣的。 – Greg 2009-08-12 19:15:31

+0

添加了更正 – 2009-08-12 19:20:09

+0

感謝您的分析! – PaulG 2009-08-12 19:56:27