网络攻防:wordpress被黑客爆破密码时的对策
症状1——/xmlrpc.php爆破
在wordpress的日志插件里发现大量登陆尝试,来自各种IP,查看docker logs发现大量类似”POST /xmlrpc.php HTTP/1.0″这样的请求。
一、xmlrpc.php 是什么?
xmlrpc.php 是 WordPress 自带的一个远程接口文件。
协议:XML-RPC
作用:允许 “不通过网页” 来远程操作 WordPress
诞生背景:移动端 / 桌面客户端时代
文件位置:/wordpress/xmlrpc.php
二、它本来是干嘛用的?(正常用途)
远程发文章 / 管理网站
例如:WordPress 官方手机 App,老式博客客户端(Windows / macOS)
它可以做:登录,发文章,改文章,获取评论
三、那为什么黑客「特别爱」它?(核心)
因为它是完美的攻击入口,它能绕过传统登录限制
/wp-login.php:有验证码,有失败次数限制,有插件防护
xmlrpc.php: 默认无验证码,默认无登录次数限制,不走 wp-login 流程,天生就是爆破接口
四、我自己会不会「正常用到」它?
对 90% 的个人 / 博客 / 企业站,不会用到
你可以自测一下项目,如果全部都是 NO,就可以放心禁用:
| 场景 | 是否使用 |
|---|
| 用 WordPress 手机 App 发文章 | ❌ |
| 用 Jetpack | ❌ |
| 用 WordPress.com 远程管理 | ❌ |
| 依赖 Pingback | ❌ |
| 第三方博客客户端 | ❌ |
五、最佳实践:怎么处理 xmlrpc.php?
方案 1(强烈推荐):直接禁用
Nginx
location = /xmlrpc.php {
deny all;
}
方案 2:只允许自己 IP(如果你要用的话)
location = /xmlrpc.php {
allow YOUR.IP.ADDR;
deny all;
}
症状2——/wp-login.php爆破(进阶)
如果应用了上面的对策之后,日志里依然出现很多登录尝试,且都是通过wp-login.php访问的,那么说明黑客开始直接怼你的登录页面了。比较推荐的方法是限制每个IP在单位时间内的登录次数,比如一分钟达到5次就暂时禁止这个IP登录。
具体实现需要修改/etc/nginx/nginx.conf和/etc/nginx/sites-enable/你的页面配置文件:
# /etc/nginx/nginx.conf
http {
# ============= 添加部分Start =============
# 定义login_limit_key来设置让访问限制只对POST请求有效,这样用户正常用GET打开页面就不会被count,只有点击登录按钮会count
map $request_method $login_limit_key {
GET "";
POST $binary_remote_addr;
}
# 设置上限每分钟5次
limit_req_zone $login_limit_key zone=wp_login:10m rate=5r/m;
# ============= 添加部分End =============
......
}
# /etc/nginx/sites-enable/你的页面配置文件
server{
......
# ============= 添加部分Start =============
location = /wp-login.php {
limit_req zone=wp_login burst=3 nodelay; # 允许极快速度瞬时连点3次,算上上面的就是8次
limit_req_status 429;
# 以下四行用于在docker反向代理时让请求带有足够的信息,以避免加载不出css和js
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080; # 样例,请填写你自己的网站入口。另外要注意不要在最后加斜杠,那样会导致登陆页面永远被重定向到主页
}
# ============= 添加部分End =============
......
}
通过以上设置就可以让每个IP只能在一分钟内登录5次。如果需要进一步限制,可以使用fail2ban / CrowdSec来设置在一定条件下直接封禁IP。
此外,还有一个有效手段是更改登录入口url,具体原理如下:
首先WordPress 内部的登录入口永远是wp-login.php,不能真的改名。
所谓“换路径”,实际做的是:
🔁 外部访问 /my-secret-login-123 → nginx 内部转发到 /wp-login.php
同时:
🚫 直接访问 /wp-login.php→ 拒绝
这对扫描器是致命的,因为它们只会扫固定路径。
具体方法只需要基于上面的/etc/nginx/sites-enable/配置文件进行进一步修改:
server {
......
# ============= 添加部分Start =============
location = /wp-login.php {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 由于注销按钮和一些其它页面功能仍然会从浏览器访问带URI的wp-login.php,并且在访问后做一些工作,因此我们只屏蔽纯/wp-login.php,对于后面带URI的情况则全部放行。
if ($args != "") {
proxy_pass http://127.0.0.1:8080;
break;
}
# 使用307跳转而不是302,因为307代表原样重放请求,会带POST body,而302跳转不会
return 307 /my-secret-login-123;
}
location = /my-secret-login-123 {
limit_req zone=wp_login burst=3 nodelay;
limit_req_status 429;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 需要显式指定URI,否则登录按钮会直接跳转主页。
proxy_pass http://127.0.0.1:8080/wp-login.php;
}
# ============= 添加部分End =============
......
}
完成这一步之后的效果是:当黑客使用工具爆破POST /wp-login.php时,他的工具会得到一个307跳转而不是正常的POST返回值。而如果黑客已经对你针对性地使用POST /my-secret-login-123来爆破,那我们还有一分钟五次的限制可以延缓他的进攻。