本文约 4,635 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:被挂黑链的那一天
一个典型的被黑现场:某天 Google 搜索结果显示站点标题变成了”便宜伟哥”,或者百度站长平台提示”发现违规外链”。进后台一看,文章里被塞了大量隐藏链接,wp-content 下多了几个名字奇怪的 PHP 文件。
事后排查,入侵路径八成是这几条之一:
- 管理员密码太弱被撞库;
- 用了带后门的盗版商业主题/插件;
- 后台开着文件编辑器,黑客进去后直接写后门;
- 目录权限 777,任何人可写;
- 某个插件有已知漏洞且长期没更新。
这五条,全部可以用下面这份清单堵住。
原理分析:WordPress 安全的四个层次
防护要分层做,任何一层漏了都可能被突破:
- 传输层:HTTPS、安全响应头;
- 服务器层:文件权限、目录访问、PHP 执行限制;
- 应用层(WordPress):账号、更新、文件编辑、登录入口;
- 监控层:日志、文件完整性监控、备份。
只做一层是不够的。比如只在 WordPress 层禁了文件编辑器,但服务器目录是 777,黑客仍可直接写文件。
保姆级实操:20 项清单
—— 服务器与文件层 ——
1. 文件权限收紧
# 目录 755,文件 644
find /var/www/site -type d -exec chmod 755 {} \;
find /var/www/site -type f -exec chmod 644 {} \;
# wp-config.php 单独收紧
chmod 600 /var/www/site/wp-config.php
# 属主设为 Web 服务用户
chown -R www-data:www-data /var/www/site
绝对不要出现 777。
2. 禁止 uploads 目录执行 PHP
这是最有效的防后门措施之一:
location ~* ^/wp-content/uploads/.*\.php$ {
deny all;
access_log off;
}
Apache(.htaccess 放在 wp-content/uploads/ 下):
<FilesMatch "\.(php|phtml|phar)$">
Require all denied
</FilesMatch>
3. 禁止访问敏感文件
location ~* /(?:wp-config\.php|readme\.html|readme\.txt|license\.txt|\.htaccess|wp-config-sample\.php) {
deny all;
}
location ~ /\.git {
deny all;
}
location ~* \.(?:bak|old|swp|sql|log|tar\.gz)$ {
deny all;
}
4. 关闭目录浏览
autoindex off;
5. 移除版本号等指纹信息
remove_action( 'wp_head', 'wp_generator' );
add_filter( 'the_generator', '__return_empty_string' );
// 移除 CSS/JS 上的版本号
add_filter( 'style_loader_src', 'mmf_remove_ver', 9999 );
add_filter( 'script_loader_src', 'mmf_remove_ver', 9999 );
function mmf_remove_ver( $src ) {
if ( strpos( $src, 'ver=' ) ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
6. 保护 wp-includes
location ~* ^/wp-includes/[^/]+\.php$ {
deny all;
}
—— WordPress 应用层 ——
7. 禁用后台文件编辑器
define( 'DISALLOW_FILE_EDIT', true );
8. 生产环境禁止后台装插件/更新(交付客户的站点)
define( 'DISALLOW_FILE_MODS', true );
9. 强制后台 HTTPS
define( 'FORCE_SSL_ADMIN', true );
10. 关闭 XML-RPC
location = /xmlrpc.php { deny all; access_log off; }
11. 删除默认账号与无用账号
wp user list --fields=ID,user_login,roles,user_registered
# 把 admin 改名、删除不用的账号
wp user delete 3 --reassign=1
绝不要保留用户名为 admin 的账号,把 ID=1 的管理员改名:
UPDATE wp_users SET user_login = 'newadmin' WHERE ID = 1;
12. 强制强密码 + 两步验证
装插件 “Wordfence Login Security” 或 “Two Factor”,管理员强制开启 2FA。
13. 限制登录失败次数
装 Wordfence 或 Limit Login Attempts Reloaded,配成:5 次失败锁定 30 分钟,24 小时内 20 次失败锁定 24 小时。
14. 关闭用户注册(不需要会员时)
// 设置 → 常规 → 取消"任何人都可注册"
wp option update users_can_register 0
15. 隐藏登录入口
装 WPS Hide Login,改掉 /wp-login.php(详见 WordPress 登录页定制)。
16. 及时更新(最基础的防护)
wp core update
wp core update-db
wp plugin update --all
wp theme update --all
wp core check-update
开启小版本自动更新:
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
17. 删除未使用的插件和主题
wp plugin list --status=inactive --field=name
wp plugin delete akismet hello
wp theme delete twentytwentytwo
停用但没删除的插件,它的 PHP 文件仍可被直接访问执行,这是真实风险。
18. 关闭 REST API 的用户端点
add_filter( 'rest_endpoints', function( $endpoints ) {
unset( $endpoints['/wp/v2/users'] );
return $endpoints;
});
19. 数据库表前缀不要用默认的 wp_
新建站点时改掉。已有站点不建议改(风险大于收益),如果一定要改:
wp search-replace 'wp_' 'mmf_' --all-tables --dry-run # 先干跑
(实际操作风险高,需要手工处理 wp_usermeta 的 meta_key 和 wp_options 的 wp_user_roles,务必先备份。)
20. 备份与监控
# 每日自动备份数据库
0 3 * * * cd /var/www/site && wp db export /backup/db-$(date +\%F).sql --allow-root
监控文件变动:装 Wordfence 的 “File Integrity Check”,或用 aide / tripwire 系统级工具。
—— 加分项 ——
安全响应头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;
PHP 层禁用危险函数
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,eval
Web 应用防火墙
Cloudflare 免费版 + 一套 WAF 规则,能挡掉绝大部分自动化攻击。
常见踩坑与失败案例
- 案例一:站点目录 777,黑客上传了一个 PHP 后门到 uploads 并执行。如果配了”uploads 禁 PHP”,即使上传成功也执行不了。
- 案例二:用了盗版的商业主题,主题里自带后门(
functions.php里有一段 base64 编码的远程下载代码)。只用官方目录或正规渠道的插件主题。 DISALLOW_FILE_MODS开了之后自己也没法装插件:更新时临时注释掉这一行,装完再打开。- 案例三:某站所有防护都做了,但管理员账号名就是
admin且密码是admin123,被撞库进去。基础项(账号名 + 强密码 + 2FA)永远优先于花哨的加固。 - 改表前缀导致站点崩溃:
wp_usermeta里的meta_key(wp_capabilities)和wp_options里的wp_user_roles也要改,只search-replace表名会漏。老站不要动。 X-Frame-Options加了自己视频打不开:用 CSP 的frame-ancestors代替。- 加固完后台 500:Nginx 规则里的正则写错(比如
location ~* ^/wp-content/uploads/.*\.php$里的转义)。改完nginx -t验证。
总结
这份清单里性价比最高的六项是:DISALLOW_FILE_EDIT、uploads 目录禁 PHP、删除无用插件主题、管理员不用 admin + 强密码 + 2FA、关闭 XML-RPC、及时更新。它们能挡住九成以上的真实攻击。加固要分四层做:服务器层(权限 + 目录规则)、WordPress 层(常量 + 账号 + 更新)、传输层(HTTPS + 响应头)、监控层(日志 + 备份 + 文件完整性)。最后必须强调两条底线:绝不使用盗版主题插件(这是最常见后门来源),备份必须异地且定期验证可恢复(加固做得再好,也要有翻盘的底牌)。
