2009-08-12 21 views
14

WordPress 2.8.3に影響する脆弱性が最近明らかになり、パスワードを変更して管理者のアカウントをロックアウトすることができます。Wordpressの脆弱性を理解する

This postフル欠陥を詳細に記載し、関連コードスニペットを含みます。投稿にはが記載されています。パスワードリセット機能を乱用し、最初の手順をバイパスして、$ key変数に配列をサブミットして管理パスワードをリセットすることができます。

私は、PHPに詳しい人に興味があり、バグについて詳しく説明しています。

影響を受ける人は、明らかにこの欠陥を修正する新しい2.8.4リリースにupdateする必要があります。

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

誤って私の言葉のプレスインストールを更新するように警告していただきありがとうございます。 :-) –

答えて

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は、 r文字列または文字列の配列。正規表現は何も置き換えずに同じ配列を返します。

もっと

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

さて、ここから、私は振る舞うの準備方法については、WordPressのソースを読んで移動する必要があります...:$キーが空ではない(それは空の文字列の配列です)ので、これは起こります:

そこそこSQLがある空の文字列を生成通話vsprintf

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

を準備します

SELECT * user_activation_key = ''

が明らかに(私は仮定activation_keysせずに、すべてのユーザー)管理者ユーザーにマッチします$ wpdb->ユーザーから。

これはその方法です。

+0

空の配列は、空の()チェックではtrueを返しますが、key [] =を渡すことで、空の文字列を唯一の要素として持つ配列を取得します。 vpsprintf()は、サンプルコードが実際に何も指示しないように出力するのではなく、値を返します。どちらの場合も、あなたの推論は健全で、最終結果は同じです。 – Greg

+0

あなたの修正を追加しました –

+0

あなたの分析のおかげで! – PaulG