漏洞条件:
请求json参数不是接收参数的javabean及其父类中的任意属性。
意思就是:我javaben里面没有这个参数 你缺传递过来了 例如我只需要pageNum pageSize 你还传了role:admin 那么这样就有可能导致致特权升级、数据篡改、绕过安全机制
解决方案:
1、自建项目修复方案一:增加反序列化配置方案
#1、在项目的统一序列化配置中开启严格匹配模式(?如有),此处以jackson为例
@Configuration
public class JacksonConverters {
@Bean
public HttpMessageConverters JacksonHttpMessageConverters() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter
= new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
//省略其他配置开始
//反序列化的时候如果多了其他属性,抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
//省略其他配置结束
}
}
#2、统一异常捕获或者返回处增加非200状态码
/**
* 捕获反序列化异常HttpMessageNotReadableException,增加500状态码返回
* @param request 请求
* @param exception 异常对象
* @return 响应
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
public ResponseEntity<Map<String, Object>> methodHttpMessageNotReadableExceptionHandler(
HttpServletRequest request, HttpMessageNotReadableException exception) {
//按需重新封装需要返回的错误信息
WebRequest webRequest = new ServletWebRequest(request);
Map<String, Object> body = errorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());
body.put(DATA, "convert exception message to JSON");
body.put(STATUS, HttpStatus.INTERNAL_SERVER_ERROR.value());
body.put(MESSAGE, HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
body.put(SUCCESS,false);
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
}
#2、或在在其他异常拦截方法上增加状态码注解
@ResponseStatus()
2、自建项目修复方案二:签名验证
针对所有的请求增加参数签名,后端采用同样的方式对参数进行签名,比较前后端签名是否一致,伪代码如下:
#前端请求
请求 URL: http://localhost/cars/query
请求方法: POST
HTTP状态码:200
playload:{"color":"red","company":"ltl","seats":"2-2"} #正常请求
Header:sign:ErOVBda4VMFdX9aixigRslAjY0rhT7lLxy
#后端controller
@PostMapping(value = "/query")
public BaseResponse query(@RequestBody Car car){
String signFront=request.header("sign");
String signBackend=signUtils.handler(car);
if(!signBackend.equals(signFront)){
throws new ServiceErrorException("签名异常");
}
}