CSRF跨站请求伪造,CMS后台安全防护
CMS后台被恶意站点诱导管理员执行操作,是CSRF跨站请求伪造的典型场景。
本文从零开始,带你完成Token校验、Cookie属性设置和请求来源检查,最终能独立验证防御是否生效。
先搞懂CSRF怎么攻击CMS后台
CSRF(Cross-Site Request Forgery)本质是借用你的登录状态,在你不知情时向CMS后台发送请求。
比如你登录了后台,又打开了一个恶意页面,该页面里藏着一行自动提交的表单,目标正是你后台的“添加管理员”接口,浏览器会自动带上你的会话Cookie,请求就被执行了。
判断一个CMS后台是否存在CSRF风险,主要看两点:
- 敏感操作(改密码、加用户、删内容)是否只依赖Cookie识别身份,没有额外随机校验;
- 请求方式是否允许GET完成写操作。
结论:只要写操作没有随机Token或来源校验,就可以认为存在CSRF风险。
动手前确认CMS版本和可改文件
不同CMS的防御方式有差异,操作前先确认你用的是哪种,以及能否修改模板或核心文件。
- 如果是WordPress,后台路径通常是
/wp-admin/,安全插件可在后台“插件-安装插件”中搜索; - 如果是ThinkPHP、Laravel等自研或框架CMS,需要修改中间件或控制器;
- 如果是宝塔面板搭建的站点,Nginx配置文件一般在
/www/server/panel/vhost/nginx/你的域名.conf; - 确认你有服务器SSH权限或宝塔面板文件管理权限。
建议先备份数据库和网站目录,再继续操作。
关键准备:备份CMS数据库和config、application等核心目录,避免改错后无法回退。
给CMS后台加上Token校验
Token是防御CSRF最直接的手段。
原理是:表单里带一个服务器生成的随机字符串,提交时服务器比对,不一致就拒绝。
以常见的PHP CMS为例,在生成表单的模板中加入:
在接收请求的控制器开头加入校验:
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('非法请求');
}
生成Token的代码放在登录成功后:
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
注意:Token必须随会话变化,且不能出现在URL中,否则会通过Referer泄露。
设置SameSite Cookie属性
SameSite能限制跨站请求是否携带Cookie,是浏览器层面的补充防御。
在CMS的Cookie设置处添加:
setcookie('PHPSESSID', session_id(), [
'samesite' => 'Lax',
'secure' => true,
'httponly' => true
]);
Lax:允许顶级导航携带Cookie,阻止跨站POST,适合大多数CMS;Strict:最严格,但可能影响从外部链接跳转回后台的体验;secure:仅HTTPS传输,必须开启。
如果Nginx直接管理Cookie,可在配置中加入:
proxy_cookie_path / "/; SameSite=Lax; secure; HttpOnly";
结论:SameSite=Lax能拦截大部分跨站表单提交,且对后台正常使用影响最小。
用Nginx校验请求来源和方式
在Nginx层可以拦截明显异常的请求。
找到站点配置文件,在location块中加入:
if ($request_method !~ ^(GET|POST)$ ) {
return 405;
}
if ($http_referer !~ ^https?://(www\.)?你的域名\.com/) {
return 403;
}
修改后执行nginx -t检查语法,再nginx -s reload重载。
注意:Referer可能被伪造,只能作为辅助手段,不能替代Token。
验证防御是否生效
改完后必须验证,否则可能白忙。
- 打开CMS后台,右键查看登录后的表单源码,确认存在
csrf_token隐藏字段; - 用浏览器开发者工具的“网络”面板,手动删除Token后提交,应返回“非法请求”或403;
- 新建一个本地HTML文件,写一个自动提交到后台改密码接口的表单,用浏览器打开,观察是否被拒绝;
- 检查Cookie的SameSite属性,在开发者工具“应用-存储-Cookie”中确认显示Lax或Strict。
如果以上都通过,说明CSRF防御已生效。
常见问题与避坑
- Token校验失败导致后台无法登录:检查Token是否在登录后重新生成,以及表单是否遗漏隐藏字段。
- 开启SameSite后第三方登录回调异常:可暂时将回调路径排除,或改用Lax并确保是GET跳转。
- Nginx规则误拦后台Ajax:确认Referer规则没有拦截同域请求,必要时用
$http_referer为空时放行。 - 只加Token不刷新:Token应每次会话重新生成,避免固定值被猜测。
避坑核心:先备份、再小范围测试、最后全站生效,不要直接在生产环境大改。
防御CSRF不是一次性工作,建议每次CMS升级后复查Token和Cookie设置,并定期用安全扫描工具检查后台接口。
如果你正在配置CMS后台安全,按本文步骤执行后,记得用验证环节确认结果,再根据CMS类型微调。