yii 2.0.45 无官方表单验证漏洞,但因开发不当(如滥用 safe、未限定场景的 load)可能导致服务端验证绕过;修复需明确验证边界、禁用非必要自动赋值、强化服务端二次校验,并慎用 safe 属性。

Yii 2.0.45 本身**没有官方公布的“表单验证漏洞”**,但社区中曾有开发者反馈在特定场景下(如未严格配置验证规则、滥用 safe 属性、或配合动态属性赋值时)可能导致服务端验证被绕过,造成安全风险。这类问题本质是**开发使用不当引发的逻辑缺陷**,而非框架底层漏洞。修复核心在于:**明确字段验证边界、禁用不必要自动赋值、强化服务端校验逻辑**。
严格定义 rules() 中的验证场景
避免笼统使用 safe,必须为每个字段显式声明验证规则和适用场景(on 场景):
- 注册场景只验证
username、email、password,不验证status或created_at - 更新资料场景允许修改
nickname和avatar,但禁止前端传入is_admin - 示例规则写法:
public function rules()
{
return [
[['username', 'email'], 'required', 'on' => [self::SCENARIO_REGISTER, self::SCENARIO_UPDATE]],
['email', 'email'],
['username', 'string', 'min' => 3, 'max' => 25],
// 关键:敏感字段绝不放入 rules(),除非明确需要且受控
// ['is_admin', 'in', 'range' => [0], 'on' => self::SCENARIO_ADMIN_ONLY], // 仅后台内部调用才启用
];
}
禁用自动批量赋值(mass assignment)风险
在控制器中创建模型时,**永远不要直接使用 $model->load($request->post()) 而不指定场景**:
- 正确写法:使用带场景的
load(),确保只加载该场景允许的字段 -
$model->load($request->post(), '')是危险的(空场景会忽略 rules 的on限制) - 推荐写法:
$model->load($request->post(), $model::SCENARIO_REGISTER) - 更安全做法:显式接收并赋值关键字段,弃用
load()
服务端二次校验关键业务逻辑
验证规则无法覆盖所有业务约束,需在 beforeSave() 或控制器中补充判断:
- 例如用户升级权限时,不能仅靠表单字段验证,要查当前登录者是否有资格操作
- 金额类字段需校验是否为数字、是否非负、是否在合理区间(防止前端篡改字符串如
"100abc") - 关联数据合法性检查(如
category_id是否真实存在且可访问)
移除或锁定危险属性(safe 属性慎用)
若模型中定义了 public $token; 等临时字段,务必在 rules() 中**不为其声明 safe 规则**,否则可能被 load() 意外赋值:
- 错误:
['token', 'safe']→ 允许任意 POST 值注入 - 正确:通过
$model->token = Yii::$app->security->generateRandomString();代码生成,不接受用户输入 - 如确需接收(如 API token 校验),应单独从
headers或GET获取,不走load()











