后台登录接口被刷了三万次后,我才把鉴权这课补明白

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 86 浏览 0 回复

上个月监控报警,后台登录接口凌晨被刷了将近三万次。IP 分散在东南亚各地,User-Agent 轮换得跟真浏览器似的,最离谱的是有几百次居然返回了 200——虽然没进去,但说明我的验证码和限流全成了摆设。那次之后我把后台鉴权整个拆了一遍,这里记几个之前想当然、实际栽过跟头的地方。

一、Session 不是丢个 token 就完事

以前图省事,登录成功写个 cookie 存 user_id,后端每次读 cookie 验身份。这次被刷才发现,这玩意儿跟"门牌号贴在脑门上"没区别,伪造成本为零。现在改成了服务端存 Session,cookie 只存一个无规律 sid,关键操作再叠加一次二次校验。ThinkPHP 的 session 驱动默认文件存储,访问量大了记得切 Redis,不然登录态一多,/tmp 目录能给你撑爆。

二、CSRF 防护别只依赖框架自动生成的 _token

TP6 开启 csrf_token 确实方便,但我踩过一个坑:后台有处批量操作用了 AJAX 提交,前端没把 token 带进去,后端为了"兼容"临时关掉了这处校验。结果这成了突破口,攻击者直接构造表单跨站请求,虽然没拿到敏感数据,但把一批文章状态给刷乱了。现在我的做法是,所有写操作统一走验证中间件,AJAX 单独封装个方法读 meta 标签里的 token,宁可前端多写两行,也不开后门。

三、SQL 注入的"新马甲":order by 和 in 参数

预编译防住了常规的 where 条件,但有两处差点翻车。一是后台列表排序,字段名从前端传过来直接拼进 order by,框架不会帮你转义字段名;二是批量删除的 id 数组,用 implode 拼进 in() 里,如果数组元素没强制转 int,传个字符串进去照样能注入。现在排序我加了白名单映射,in 参数循环 intval 过滤,多写几行,睡得踏实。

四、权限校验粒度要打到"按钮级"

以前只做到菜单级权限,能看到页面就默认能操作页面里的功能。结果运营同事账号被盗,对方进了后台虽然看不到敏感菜单,但直接 POST 接口把提现记录给导出了。现在接口层面单独加权限中间件,每个 controller 方法标注需要的节点码,前端按钮显不显示另说,后端先把你拦住。

五、一个小习惯:关键操作留痕

登录、改密、导出、批量操作,现在全写操作日志,带 IP、UA、操作前后数据快照。不是为了抓内鬼,是出事之后能复盘攻击路径。那次被刷三万次,靠日志才定位到是从前台一处上传接口泄露了后台地址,然后定向爆破的。

写完这些回头看,全是基础得不能再基础的东西,但真到项目赶进度的时候,太容易"先上线再补"。我的建议是,后台鉴权这块别留 TODO,一旦出事就是裸奔。你们有没有类似被刷或者绕过的经历?欢迎交流,我这边还有两杯咖啡的清醒时间。

评论0
回复 · 0
还没有回复
微信客服 微信客服