一句话总结:批量赋值漏洞 ,指框架自动把外部传入的所有参数直接绑定到实体类/对象,攻击者借此篡改本不该被修改的敏感字段。
一、通俗理解
举个最常见场景:用户注册/修改个人资料接口
- 业务只允许用户修改:
nickname、avatar - 但数据库实体还有敏感字段:
is_admin(是否管理员)、user_role、balance(余额)、password - 后端框架开启全字段自动绑定,前端传什么参数,就全部赋值给对象入库
攻击者请求时额外带上敏感参数:
http
POST /update-user
{
"nickname": "test",
"avatar": "xxx.jpg",
"is_admin": true // 恶意新增字段
}
后端没做过滤,直接执行更新 → 普通用户变成管理员,漏洞形成。
二、常见出现场景
主流 MVC/ORM 框架几乎都有这个特性,也是高危点:
- Java :Spring Boot
@ModelAttribute、MyBatis-Plus 自动赋值、JPA - Python:Django ORM、Flask-SQLAlchemy、Peewee
- PHP :Laravel
$fillable/$guarded、ThinkPHP - Node.js:Sequelize、Mongoose
典型代码示例(Python Flask + SQLAlchemy 危险写法)
python
# 危险:直接把前端所有参数塞给用户对象
@app.route("/user/update", methods=["POST"])
def update_user():
user = User.query.get(1)
# 批量赋值,前端传啥改啥
for k, v in request.form.items():
setattr(user, k, v)
db.session.commit()
return "ok"
攻击者传 is_admin=1,直接提权。
三、危害等级
- 越权提权:普通用户 → 管理员
- 数据篡改:修改余额、权限、状态、密码
- 越权操作:篡改他人数据、关闭账号等 属于 OWASP 常见高危漏洞。
四、标准修复方案(按推荐优先级)
1. 白名单(最推荐,通用)
只允许指定字段赋值,拒绝所有未知参数。
python
# 只允许这两个字段
allow_fields = ["nickname", "avatar"]
for k, v in request.form.items():
if k in allow_fields:
setattr(user, k, v)
2. 框架原生限制(框架专属)
Python Django
显式指定允许字段,禁止全量绑定:
python
# 模型层面限制
class User(models.Model):
nickname = models.CharField()
is_admin = models.BooleanField(default=False)
# 视图/表单只接收指定字段
form = UserForm(request.POST)
if form.is_valid():
form.save(commit=False)
PHP Laravel
$fillable:白名单(允许批量赋值的字段)$guarded = []是高危(允许所有字段)
php
class User extends Model
{
// 安全:仅允许这两个字段批量赋值
protected $fillable = ['nickname', 'avatar'];
}
Java Spring Boot
使用 @DataBinder、@InitBinder 排除敏感字段:
java
@InitBinder
public void initBinder(DataBinder binder) {
// 黑名单:禁止绑定敏感字段
binder.setDisallowedFields("isAdmin", "userRole", "balance");
}
3. 使用 DTO/入参实体(企业项目标准做法)
接口只接收 DTO 对象,不和数据库实体直接绑定。
- 前端参数 → DTO(仅业务字段)→ 手动赋值给 DB 实体
- 彻底隔离,从架构上杜绝批量赋值。
五、快速识别漏洞特征
- 接口直接使用数据库实体类接收前端参数
- 代码存在
setattr、循环遍历请求参数赋值 - 框架开启无限制批量绑定 (如 Laravel
$guarded = []) - 接口未做字段过滤、未使用白名单
六、精简总结
- 本质:外部可控参数 → 无过滤批量赋值到数据模型
- 核心风险:篡改敏感字段、提权、越权
- 最简修复 :字段白名单 / 单独使用入参 DTO,不要用数据库实体直接接收请求参数。