Yii2中CSRF Token验证异常:攻击者可通过GET请求绕过验证
问题分析:GET请求绕过Yii2 CSRF验证的原因
问题场景
已在Yii2主配置中开启CSRF验证,核心配置如下:
'components' => [ 'request' => [ 'enableCsrfValidation' => true, 'enableCookieValidation' => true, 'cookieValidationKey' => '[somerandomstring]', 'csrfParam' => '_csrf-backend', 'hostInfo' => YII_ENV_PROD ? Yii::$app->params['hostInfo'] : null, 'csrfCookie' => [ 'httpOnly' => true, 'secure' => YII_ENV_PROD, 'sameSite' => 'Lax', ], ], ]
控制器actionIndex用于修改用户全名,代码实现:
public function actionIndex() { $model = new ProfileForm(); $model->fullName = Yii::$app->user->identity->full_name; if ($model->load(Yii::$app->request->post()) && $model->save()) { Yii::$app->session->setFlash('success', 'Profile updated successfully.'); return $this->refresh(); } return $this->render('index', [ 'model' => $model, ]); }
视图通过ActiveForm生成表单,渲染后表单及请求头均包含CSRF参数与token,但渗透测试发现:攻击者无需提交CSRF token,通过GET请求即可修改用户全名,且其他Gii生成的控制器/动作也存在相同问题。
核心原因
Yii2框架默认仅对POST/PUT/DELETE/PATCH等非安全HTTP方法触发CSRF验证,GET请求被定义为"安全方法"(HTTP规范中仅用于获取数据,不应修改服务器状态),因此默认跳过CSRF校验。
你的场景中出现漏洞的关键在于:
- 修改数据的业务逻辑未限制请求方法:
actionIndex未明确禁止GET请求访问,攻击者可构造GET请求触发数据修改流程 - 违背HTTP规范:将修改用户数据的操作暴露给GET请求,而GET请求本身不受CSRF保护,攻击者可通过诱导用户点击恶意链接完成未授权操作
解决方法
1. 限制动作的请求方法(推荐)
通过VerbFilter行为明确指定修改类动作仅接受POST等非安全方法,在控制器中添加:
public function behaviors() { $behaviors = parent::behaviors(); $behaviors['verbs'] = [ 'class' => \yii\filters\VerbFilter::class, 'actions' => [ 'index' => ['post'], // 仅允许POST请求访问当前修改动作 // 其他需要保护的动作也需添加限制,如update/delete等 ], ]; return $behaviors; }
2. 代码层强化请求方法判断
即使动作未配置方法限制,也需在业务逻辑中严格校验请求类型:
// 仅在POST请求下执行数据修改 if (Yii::$app->request->isPost && $model->load(Yii::$app->request->post()) && $model->save()) { Yii::$app->session->setFlash('success', 'Profile updated successfully.'); return $this->refresh(); }
3. 检查Gii生成的代码
Gii默认生成的CRUD动作中,更新/删除等修改类动作会自动限制请求方法,但自定义动作(如本例的actionIndex)需手动添加限制,避免GET请求触发数据变更。
4. 不推荐方案:强制对GET请求开启CSRF验证
若业务特殊需求必须使用GET修改数据,可在请求组件中配置扩展CSRF验证的方法,但此方式违背HTTP规范,可能引发其他问题:
'request' => [ 'enableCsrfValidation' => true, 'csrfValidationMethods' => ['POST', 'PUT', 'DELETE', 'GET'], // 其他原有配置 ]
内容的提问来源于stack exchange,提问作者Prabowo Murti
相关产品推荐
相关产品推荐

