ThinkPHP应用是否存在CSRF漏洞取决于是否正确启用并配置防伪机制;5.0及之前需手动实现,5.1+虽支持token但默认不启用,常见问题包括表单未输出token、API未校验、token未绑定会话等。

ThinkPHP(TP)框架在5.0及之前版本中默认未内置CSRF防护机制,开发者需手动实现;而从5.1开始引入了token验证支持,但是否启用、如何配置、是否绑定会话,完全取决于开发人员。因此,TP应用是否存在CSRF漏洞,不取决于框架本身“有没有”,而取决于项目中“有没有正确使用”防伪机制。
TP中CSRF漏洞的常见成因
多数TP项目的CSRF问题源于开发习惯和配置疏忽:
- 表单提交未调用
csrf_token()或未在控制器中校验think\facade\Request::token() - 使用
Request::param()直接接收关键参数(如修改密码、转账金额),跳过CSRF中间件或验证逻辑 - API接口(尤其是
POST /api/user/update类路由)未开启checkToken中间件,也未校验X-CSRF-TOKEN头 - Token生成后未绑定用户会话(如用
md5(uniqid())硬编码生成),导致令牌可跨账号复用 - 前端将Token写入Cookie而非DOM,攻击者可通过XSS读取并用于伪造请求
TP典型绕过方式(结合实战)
即使项目启用了Token,仍可能被绕过:
-
GET型操作未防护:TP默认对
GET请求不强制校验Token,若重置邮箱、注销等敏感操作走GET,直接构造URL即可触发 - Token未随会话刷新:登录后Token未更新,攻击者可提前获取有效Token,长期复用
-
校验逻辑被跳过:部分项目仅在
update方法开头加校验,但通过路由别名(如/user/edit→user/save)或方法重载绕过 -
Referer白名单宽松:自定义中间件只检查
strpos($_SERVER['HTTP_REFERER'], 'yourdomain.com'),可构造https://evil.com/yourdomain.com/xxx绕过
检测与验证方法
针对TP项目,可按以下步骤快速判断是否存在可利用CSRF:
- 抓取一个修改类请求(如密码修改),观察请求体是否含
_token或__token字段;若无,基本确认缺失防护 - 有Token时,尝试删除该参数重发请求;若仍成功,说明服务端仅“存在即校验”,未做严格验证
- 复制完整请求,在Burp中右键 → Engagement tools → Generate CSRF PoC,勾选Auto-submit script,生成HTML后本地打开测试
- 检查响应头是否含
Set-Cookie: think_csrf_token=...且未设SameSite=Strict,这意味Token可能被第三方页面携带
防御建议(TP适配版)
TP项目应避免“手写Token逻辑”,优先使用框架能力:
- 在模板中统一使用
{:token()}或{:csrf_token()}输出隐藏域,确保每次渲染生成新Token - 在控制器基类或中间件中调用
\think\facade\Request::isCheckToken(true),并确保token_name与前端一致 - API场景下,配合
header('X-CSRF-TOKEN: '.$token)+ 前端axios.defaults.headers.common['X-CSRF-TOKEN']使用 - 启用
same_site配置:'cookie' => ['same_site' => 'Strict'](TP6.1+),阻断跨站Cookie携带 - 关键操作(如改密、删数据)强制二次验证(短信/邮箱验证码),不依赖单一Token机制


















