如何修复Newtonsoft JSON下的Mass Assignment不安全绑定配置漏洞
Mass Assignment漏洞防范方案及Dummy字段生效原理
为什么加[JsonIgnore]的Dummy字段能消除扫描报错?
这其实是Fortify扫描规则判定逻辑导致的假修复:
- 原始的
StepDefinition类没有任何序列化控制注解(比如[JsonIgnore]、[JsonProperty]),Fortify会判定所有公开属性都可能被攻击者通过批量赋值篡改,触发漏洞告警。 - 当你添加带
[JsonIgnore]的Dummy字段后,扫描器检测到你对序列化做了显式控制,就认为你已经处理了批量赋值风险,从而停止告警。但本质上这个Dummy字段没解决实际问题——敏感字段(比如IsArchived、IsReadOnly、UserId)仍然会被Newtonsoft反序列化赋值,攻击者还是可以构造请求修改这些字段。
正确的防范方法
1. 使用DTO(数据传输对象)【最推荐】
不要直接把数据库实体类作为接口参数,专门定义只包含允许用户传入字段的DTO,严格控制输入范围,敏感的系统维护字段在Controller里手动赋值:
// 定义创建用的DTO,只暴露允许用户输入的字段 public class StepDefinitionCreateDto { public string Name { get; set; } public string Description { get; set; } public bool IsAutomated { get; set; } public string ActionName { get; set; } public bool HasParameters { get; set; } } // 修改Controller方法 [HttpPost] [Route("")] public async Task<IActionResult> PostAsync(Guid tenantId, StepDefinitionCreateDto dto) { // 手动将DTO字段映射到实体类,同时赋值系统字段 var stepDefinition = new StepDefinition { TenantId = tenantId, Name = dto.Name, Description = dto.Description, IsAutomated = dto.IsAutomated, ActionName = dto.ActionName, HasParameters = dto.HasParameters, // 从当前登录用户获取UserId,避免前端传入 UserId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)), // 系统默认值,不允许前端修改 IsArchived = false, IsReadOnly = false, CanDelete = true }; // 后续执行保存数据库的逻辑 // ... return Ok(stepDefinition); }
2. 显式标记允许序列化的字段
如果必须使用实体类作为参数,用Newtonsoft的注解显式指定哪些字段可以被反序列化,其他字段默认忽略:
[JsonObject(MemberSerialization.OptIn)] // 开启“仅显式标记的字段参与序列化”模式 public class StepDefinition { // 这些系统字段不允许前端传入,不标记[JsonProperty] public Guid StepDefinitionId { get; set; } public Guid TenantId { get; set; } public bool IsArchived { get; set; } public bool IsReadOnly { get; set; } public bool CanDelete { get; set; } public Guid UserId { get; set; } public virtual ICollection<StepOutcome> StepOutComes { get; set; } // 允许前端传入的字段,标记[JsonProperty] [JsonProperty] public string Name { get; set; } [JsonProperty] public string Description { get; set; } [JsonProperty] public bool IsAutomated { get; set; } [JsonProperty] public string ActionName { get; set; } [JsonProperty] public bool HasParameters { get; set; } }
3. 使用[Bind]属性限制绑定字段(不推荐)
在ASP.NET Core中,可以通过[Bind]属性指定允许模型绑定的字段,但这种方式不如DTO安全,因为实体类的所有字段仍然可见:
[HttpPost] [Route("")] // 只绑定指定的字段,其他字段会保持默认值 public async Task<IActionResult> PostAsync(Guid tenantId, [Bind("Name,Description,IsAutomated,ActionName,HasParameters")] StepDefinition model) { // 手动赋值系统字段 model.TenantId = tenantId; model.UserId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); model.IsArchived = false; // ... // 后续保存逻辑 return Ok(model); }
内容的提问来源于stack exchange,提问作者ckv
相关产品推荐
相关产品推荐

