2009-08-12 114 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