两处安全缺陷

这是 WordPress 长期存在的安全缺陷 ,只需要一行参数就能够查询注册用户的登录账号,包括管理员。

如果你用的也是 Wordpress,可以通过下面的方法自查。

//把参数加在主域名后提交
?author=1

比如 https://geekufo.com/?author=1  ,这里的 1 就代表管理员 user_id 的默认值。

下图中的 admintest ,就是在截图演示期间,我网站的真实管理员账号。

这位站长,你的账号暴露了-极客飞船

即使不通过 author 参数查询,只要是开放了作者归档页的主题,通过作者头像或更多文章链接也能看到:

这位站长,你的账号暴露了-极客飞船

此外,这个问题不仅仅存在于文章的归档页,默认的评论代码结构也会暴露用户名:

这位站长,你的账号暴露了-极客飞船

只要是注册用户发表的留言或回复都会显示用户名。

这无疑为暴力猜解提供了极大便利,尤其是还在使用默认后台 URL  //域名/wp-login.php  的网站。

修复工作

WordPress 会为每一个注册用户分配唯一的 user_id,在 WP 的函数中对应 author_id ,我们可以将「输出的用户名」改成「输出用户 ID」,这样就达到了隐藏用户名的目的。

将以下代码添加到主题的 functions.php 文件中:

/** 隐藏作者归档用户名第一步:
*改变查询方式,author_nicename 变 author_id
*感谢 @倡萌 分享
*/
add_filter( 'author_link', 'geekufo_author_link', 10, 2 );
function geekufo_author_link( $link, $author_id) {
global $wp_rewrite;
$author_id = (int) $author_id;
$link = $wp_rewrite->get_author_permastruct();
if ( empty($link) ) {
$file = home_url( '/' );
$link = $file . '?author=' . $author_id;
} else {
$link = str_replace('%author%', $author_id, $link);
$link = home_url( user_trailingslashit( $link ) );
}
return $link;
}

/** 隐藏作者归档用户名第二步:
* 重新定义跳转规则,rewrite 后把用户名替换为 id
*感谢 @倡萌 分享
*/
add_filter( 'request', 'geekufo_author_link_request' );
function geekufo_author_link_request( $query_vars ) {
if ( array_key_exists( 'author_name', $query_vars ) ) {
global $wpdb;
$author_id=$query_vars['author_name'];
if ( $author_id ) {
$query_vars['author'] = $author_id;
unset( $query_vars['author_name'] );
}
}
return $query_vars;
}

然后再把评论部分的用户名隐藏掉:

/**隐藏评论代码里的用户名
*感谢 @龙笑天下 分享
*/
function geekufo_comment_class($content){
$pattern = "/(.*?)([^>]*)author-([^>]*)(.*?)/i";
$replacement = '$1$4';
$content = preg_replace($pattern, $replacement, $content);
return $content;
}
add_filter('comment_class', 'geekufo_comment_class');
add_filter('body_class', 'geekufo_comment_class');

还可以顺手改下后台登录的 URL

//隐藏后台原 wp-admin 路径
add_action('login_enqueue_scripts','login_protection');  
function login_protection(){  
    if($_GET['关键字 1'] != '关键字 2')header('Location: http(s)://自定义页面');
}

这段代码的效果是,只有输入 //域名/wp-login.php?关键字 1 = 关键字 2 时,才会显示登录界面,如果不是就跳转到 自定义页面 ,比如 404 提示。

小结和参考资料

上述的 WordPress 默认配置可以在 /wp-includes/ 目录 author-template.php 和 comment-template.php  中查阅到,其中最主要的函数为 author_nicenameauthor_id 

另外,经查阅数据库可以获知:

user_loginuser_nicename 一样;

nickname 对应「昵称」;

first_name 对应 「名称」;

last_name 对应 「姓氏」;

display_name 对应 「公开显示为」。

所以理论上也可以是「输出用户名」改成「输出昵称」或「输出姓氏」,但还是推荐具有唯一性的 user_id,即使用户多也可以避免重复。

本文参考资料:
https://www.wpdaxue.com/redirect-author-archive-link-to-about-page.html
https://www.wpdaxue.com/use-nickname-for-author-slug.html
https://www.wpdaxue.com/use-user-id-for-author-slug.html
https://www.wpdaxue.com/avoid-disclosing-your-admin-login-username.html