一、author页面地址

author页面地址为 http://yoursite/?author=1 ID是自增的

请求这个地址会 301 到一个url,这个url里包含了作者的用户名。虽然不算漏洞,还是给了爆破者很大的便利。

301指向的url :  .../author/你的后台登录用户名

解决方案

1.在主题代码里实现,只要访问主页url后头有author参数就让他跳到主页

将下面的代码添加到当前主题的  functions.php  文件:

function my_author_link() {
return home_url('/' );
}
add_filter('author_link','my_author_link');

2.通过.htaccess文件添加301重定向来隐藏后台用户名

在 .htaccess 文件里加入

redirect  /(这里还有path的请自行添加)/author/你的后台登录用户名/ http://yoursite/

上面这段代码意思为:

将 http://yoursite/.../author/你的后台登录用户名/

跳转至

http://yoursite/

当我们输入http://yoursite/?author=1 时会先跳转至http://yoursite/.../author/你的后台登录用户名/,所以将跳转后的链接做301重定向即可。

此方法也可以在你的web服务器配置文件中实现

二.xmlrpc.php

xmlrpc 是 WordPress 中进行远程调用的接口,而使用 xmlrpc 调用接口进行账号爆破在很早之前就被提出并加以利用。xmlrpc登录接口默认没有验证码,最大错误尝试次数限制等。利用xmlrpc.php提供的接口尝试猜解用户的密码,可以绕过wordpress对暴力破解的限制。

1.攻击方式

攻击的方式直接POST以下数据到xmlrpc.php

<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall> <methodName>wp.getUsersBlogs</methodName> <params> <param><value>username</value></param> <param><value>password</value></param> </params>
</methodCall>

其中username字段是预先收集的用户名。password是尝试的密码。关于getUsersBlogs接口的更多信息可以参考官方的指南  。如果密码正确,返回为:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>isAdmin</name>
<value>
<boolean>1</boolean>
</value>
</member>
<member>
<name>url</name>
<value>
<string>http://yoursite/</string>
</value>
</member>
<member>
<name>siteid</name>
<value>
<string>1</string>
</value>
</member>
<member>
<name>SiteName</name>
<value>
<string>Your Site</string>
</value>
</member>
<member>
<name>xmlrpc</name>
<value>
<string>http://yoursite/xmlrpc.php</string>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</param>
</params>
</methodResponse>

错误返回:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value>
<int>403</int>
</value>
</member>
<member>
<name>faultString</name>
<value>
<string>用户名或密码不正确。</string>
</value>
</member>
</struct>
</value>
</fault>
</methodResponse>

近日 SUCURI 发布文章介绍了如何利用 xmlrpc 调用接口中的 system.multicall 来提高爆破效率,使得成千上万次的帐号密码组合尝试能在一次请求完成,极大的压缩请求次数,在一定程度上能够躲避日志的检测。

2.原理分析

WordPress 中关于 xmlrpc 服务的定义代码主要位于 wp-includes/class-IXR.php 和 wp-includes/class-wp-xmlrpc-server.php 中。基类 IXR_Server 中定义了三个内置的调用方法,分别为 system.getCapabilities,system.listMethods 和 system.multicall,其调用映射位于 IXR_Server 基类定义中:

<?php
function setCallbacks()
{
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
$this->callbacks['system.listMethods'] = 'this:listMethods';
$this->callbacks['system.multicall'] = 'this:multiCall';
}

而基类在初始化时,调用  setCallbacks()  绑定了调用映射关系:

<?php
function __construct( $callbacks = false, $data = false, $wait = false )
{
$this->setCapabilities();
if ($callbacks) {
$this->callbacks = $callbacks;
}
$this->setCallbacks(); // 绑定默认的三个基本调用映射
if (!$wait) {
$this->serve($data);
}
}

再来看看 system.multicall 对应的处理函数:

<?php
function multiCall($methodcalls)
{
// See http://www.xmlrpc.com/discuss/msgReader$1208
$return = array();
foreach ($methodcalls as $call) {
$method = $call['methodName'];
$params = $call['params'];
if ($method == 'system.multicall') {
$result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
} else {
$result = $this->call($method, $params);
}
if (is_a($result, 'IXR_Error')) {
$return[] = array(
'faultCode' => $result->code,
'faultString' => $result->message
);
} else {
$return[] = array($result);
}
}
return $return;
}

可以从代码中看出,程序会解析请求传递的 XML,遍历多重调用中的每一个接口调用请求,并会将最终有调用的结果合在一起返回给请求端。

这样一来,就可以将500种甚至是10000种帐号密码爆破尝试包含在一次请求中,服务端会很快处理完并返回结果,这样极大地提高了爆破的效率,利用多重调用接口压缩了请求次数,10000种帐号密码尝试只会在目标服务器上留下一条访问日志,一定程度上躲避了日志的安全检测。

通过阅读 WordPress 中 xmlrpc 相关处理的代码,能大量的 xmlrpc 调用都验证了用户名和密码:

<?php
if ( !$user = $this->login($username, $password) )
return $this->error;

通过搜索上述登录验证代码可以得到所有能够用来进行爆破的调用方法列表如下:

wp.getUsersBlogs, wp.newPost, wp.editPost, wp.deletePost, wp.getPost, wp.getPosts, wp.newTerm, wp.editTerm, wp.deleteTerm, wp.getTerm, wp.getTerms, wp.getTaxonomy, wp.getTaxonomies, wp.getUser, wp.getUsers, wp.getProfile, wp.editProfile, wp.getPage, wp.getPages, wp.newPage, wp.deletePage, wp.editPage, wp.getPageList, wp.getAuthors, wp.getTags, wp.newCategory, wp.deleteCategory, wp.suggestCategories, wp.getComment, wp.getComments, wp.deleteComment, wp.editComment, wp.newComment, wp.getCommentStatusList, wp.getCommentCount, wp.getPostStatusList, wp.getPageStatusList, wp.getPageTemplates, wp.getOptions, wp.setOptions, wp.getMediaItem, wp.getMediaLibrary, wp.getPostFormats, wp.getPostType, wp.getPostTypes, wp.getRevisions, wp.restoreRevision, blogger.getUsersBlogs, blogger.getUserInfo, blogger.getPost, blogger.getRecentPosts, blogger.newPost, blogger.editPost, blogger.deletePost, mw.newPost, mw.editPost, mw.getPost, mw.getRecentPosts, mw.getCategories, mw.newMediaObject, mt.getRecentPostTitles, mt.getPostCategories, mt.setPostCategories

这里是用参数传递最少获取信息最直接的 wp.getUsersBlogs 进行测试,将两次帐号密码尝试包含在同一次请求里,构造 XML 请求内容为:

<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>system.multicall</methodName>
<params><param>
<value><array><data>
<value><struct>
<member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member>
<member><name>params</name><value><array><data>
<value><string>admin</string></value>
<value><string>admin888</string></value>
</data></array></value></member>
</struct></value> <value><struct>
<member><name>methodName</name><value><string>wp.getUsersBlogs</string></value></member>
<member><name>params</name><value><array><data>
<value><string>guest</string></value>
<value><string>test</string></value>
</data></array></value></member>
</struct></value>
</data></array></value>
</param></params>
</methodCall>

将上面包含两个子调用的 XML 请求POST至 xmlrpc 服务端入口,若目标开启了 xmlrpc 服务会返回类似如下的信息:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><array><data>
<value><array><data>
<value><struct>
<member><name>isAdmin</name><value><boolean>1</boolean></value></member>
<member><name>url</name><value><string>http://172.16.96.130/xampp/wordpress-4.3.1/</string></value></member>
<member><name>blogid</name><value><string>1</string></value></member>
<member><name>blogName</name><value><string>WordPress 4.3.1</string></value></member>
<member><name>xmlrpc</name><value><string>http://172.16.96.130/xampp/wordpress-4.3.1/xmlrpc.php</string></value></member>
</struct></value>
</data></array></value>
</data></array></value>
<value><struct>
<member><name>faultCode</name><value><int>403</int></value></member>
<member><name>faultString</name><value><string>用户名或密码不正确。</string></value></member>
</struct></value>
</data></array>
</value>
</param>
</params>
</methodResponse>

从结果中可以看到在同一次请求里面处理了两种帐号密码组合,并以集中形式将结果返回,通过该种方式可以极大地提高帐号爆破效率。

3.防护建议

1) 通过配置 Apache、Nginx 等 Web 服务器来限制 xmlrpc.php 文件的访问;

这里举例一个nginx的

location =/xmlrpc.php {
deny all;
}

2) 添加防护代码至WordPress配置文件

在wordpress的配置文件  wp-config.php  中添加如下代码

add_filter('xmlrpc_enabled', '__return_false');

3) 从官方插件库中安装 Disable XML-RPC https://wordpress.org/plugins/disable-xml-rpc/ 并启用。

4) 在不影响站点运行的情况下可以直接删除 xmlrpc.php 文件。(不建议)

三. wordpress 后台默认地址

后台默认地址是 http://yoursite/wp-login.php 这个地址很容易让有意爆破者,或者爆破工具(比如:wpscan) 找到,我们需要修改掉这个默认地址。

网上找到的很多做法是这样。在主题的 functions.php 里添加以下代码

function login_protection() {
if($_GET['word'] !='press')
header('Location: /');
}
add_action('login_enqueue_scripts','login_protection');

这样一来,后台登录的唯一地址就是 http://yoursite/wp-login.php?word=press,如果不是这个地址,就会自动跳转到 http://yoursite/

但是,这并不能完全解决爆破入口的问题,懂一些http的人可以通过post来爆破该入口。

解决方案:

这里推荐三个插件
WPS Hide Login: 修改登录路由,来达到隐藏wordpress登录入口暴露的问题
WPS Limit Login: 限制后台登录试错次数,阻止黑客的IP地址

Brute Force Login Protection :跟 WPS Limit Login 功能差不多

四.restAPI

wordpress的restAPI也是可以暴露用户名的

GET http://yoursite/wp-json/wp/v2/users

[
{
"id": ,
"name": "nickname",
"url": "",
"description": "",
"link": "http://yoursite/author/username",
"slug": "username",
"avatar_urls": {
"": "https://secure.gravatar.com/avatar/hashNumber?s=24&d=retro&r=g",
"": "https://secure.gravatar.com/avatar/hashNumber?s=48&d=retro&r=g",
"": "https://secure.gravatar.com/avatar/hashNumber?s=96&d=retro&r=g"
},
"meta": [],
"_links": {
"self": [
{
"href": "http://yoursite/wp-json/wp/v2/users/1"
}
],
"collection": [
{
"href": "http://yoursite/wp-json/wp/v2/users"
}
]
}
}
]

"link": "http://yoursite/author/username"  中  username  就是后台用户名了

解决方案:

方法一: 代码中禁止

在wordpress的主题所在 functions.php 中添加如下代码

过滤users端点,使未登录用户不能访问

add_filter( 'rest_endpoints', function( $endpoints ){
if(!is_user_logged_in()) {
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'] );
}
if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
}
}
return $endpoints;
});

或者

完全禁用未登录用户获取api

/*禁用未登录的用户*/
function rest_only_for_authorized_users($wp_rest_server) {
if ( !is_user_logged_in() ) {
wp_die('非法操作!');
}
}
add_filter('rest_api_init', 'rest_only_for_authorized_users', 99);

两种方法,二选一

方法二:通过Web 服务器限制restAPI的访问

这里用nginx来举例子,其他服务器的设置请自行研究

全面禁用restAPI
location ~* /wp/v2/(.*) {
deny all;
}
只禁用users端点
location ~* /wp-json/wp/v2/users(\/)?(.*)? {
deny all;
}

方法三:WPS Bidouille插件

WPS Bidouille  中有个功能,可以直接在后台禁用掉restAPI的用户端点,所以,你只需要将用户端点在后台禁用即可。也可直接禁用REST API。
此外,该插件还支持禁用作者页面和作者链接,省掉了本文第一节的代码操作。其他功能详见这里

参考文章

  1. http://blog.knownsec.com/2015/10/wordpress-xmlrpc-brute-force-amplification-attack-analysis/
  2. https://blog.csdn.net/u013474104/article/details/78703122

wordpress 暴力破解防范的更多相关文章

  1. 防止WordPress利用xmlrpc.php进行暴力破解以及DDoS

    早在2012 年 12 月 17 日一些采用 PHP 的知名博客程序 WordPress被曝光存在严重的漏洞,该漏洞覆盖WordPress 全部已发布的版本(包括WordPress 3.8.1).该漏 ...

  2. WordPress防暴力破解:安全插件和用.htpasswd保护WordPress控制面板

    正在用Wordpress的博主们一定知道最近全球兴起的一波黑客锁定Wordpress暴力破解控制面板密码的风波了,据CloudFlare执行长Matthew Prince所说,所谓的暴力密码攻击是输入 ...

  3. 暴力破解FTP服务器技术探讨与防范措施

    暴力破解FTP服务器技术探讨与防范措施 随着Internet的发展出现了由于大量傻瓜化黑客工具任何一种黑客攻击手段的门槛都降低了很多但是暴力破解法的工具制作都已经非常容易大家通常会认为暴力破解攻击只是 ...

  4. DVWA 黑客攻防演练(二)暴力破解 Brute Froce

    暴力破解,简称"爆破".不要以为没人会对一些小站爆破.实现上我以前用 wordpress 搭建一个博客开始就有人对我的站点进行爆破.这是装了 WordfenceWAF 插件后的统计 ...

  5. ssh防止暴力破解之fail2ban

    1.利用sshd服务本身防止暴力破解 2.sshd服务防止暴力破解和fail2ban使用方法 先说说一般的防范措施: 方法1: 1.密码足够复杂: 密码的长度要大于8位最好大于14位.密码的复杂度是密 ...

  6. 利用ModSecurity防御暴力破解

    利用ModSecurity防御暴力破解 from:http://www.freebuf.com/articles/web/8749.html 2013-04-18 共553248人围观 ,发现 12 ...

  7. 拒绝ssh远程暴力破解

    拒绝ssh远程暴力破解 简介 在网络技术日益发展的今天,网络上的安全问题日益严重.当你在公网上使用Linux服务器时,很有可能你的服务器正在遭受ssh暴力破解. 曾经有一次我的同伴将给客户提供监控服务 ...

  8. ModSecurity防御暴力破解

    http://www.modsecurity.org/ ModSecurity防御暴力破解 在阅读本文前,先简单了解下什么是ModSecurity,ModSecurity是一个入侵探测与阻止的引擎.它 ...

  9. Linux CentOS 防止SSH暴力破解

    一. 问题的发现 昨晚苦逼加班完后,今早上班继续干活时,SSH连接服务器发现异常的提示,仔细看了一下吓一小跳,昨晚9点钟到现在,一夜之间被人尝试连接200+,慌~~~ 1. 速度查一下log [roo ...

随机推荐

  1. Angular7.1.4+Typescript3.1框架学习(一)

    起因:学习ionic4之前先学习下angular+ts 以win10为开发平台:当前最新版本为angular7;根据官网资料做如下总结: 1. angular安装 前提:Node.js 的 8.x 或 ...

  2. C# Winform 自适应

    参考:http://yefenme.blog.163.com/blog/static/13069770420132283644288/ 自适应首先考虑的是AutoScaleMode属性设置,其中=DP ...

  3. 简易OA漫谈之工作流设计(一个Demo),完成6年前的一个贴子

    6年前在腾讯做OA,那时写了两篇心得. https://www.cnblogs.com/wangxiaohuo/archive/2012/08/22/2650893.html https://www. ...

  4. struts标签怎么判断request里的属性是否为空 <s:if test="${list==null}"> </s:if>

    <s:if test="${weigou}==999"> //错误的 ${list==null} ,$实在strtus的配置文件中取值用的,不是在jsp页面里取值的的吧 ...

  5. day1 登录

    #!/usr/bin/env python #Author:windtalker import os, getpass import sqlite3 from time import ctime pr ...

  6. Nuget连接失败的问题

    ---恢复内容开始--- .net 项目开发管理中我们经常使用Nuget管理我们的类库.由于某些原因 nuget v3的镜像源https://api.nuget.org/v3/index.json 经 ...

  7. Vue的学习

    1.Vue是什么 参考Vue官网,一套用于构建用户界面的渐进式框架. 2.什么是渐进式框架 引用大神的话:“它给你提供足够的optional,但并不主张很多required,也不多做职责之外的事!这就 ...

  8. Python_Mix*re模块,元字符,量词

    模块: 模块就是一组功能的集合,你要和某个东西打交道,而这个东西本身和Python没有关系,这个东西本身就存在,Python提供了一个功能的集合,专门负责和这个东西打交道. 模块的类型: 内置模块 不 ...

  9. 使用labelme制作自己的数据集

    # python3 conda create --name=labelme python=3.6 source activate labelme # conda install -c conda-fo ...

  10. math-2人博弈

    问题描述: 100根火柴,2人轮流取,每人每次只能取1-7根,取走最后一根火柴的人获胜.问有没有一种策略肯定能够获胜?该策略具体:先取or后取,怎么取? 思维过程: step1:题目问的很明显,所以肯 ...