API成批分配漏洞介绍
API 特定:可利用性 2
利用通常需要了解业务逻辑、对象关系和 API 结构。 在 API 中利用批量分配更容易,因为按照设计,它们公开了应用程序的底层实现以及属性名称。
安全弱点:
现代框架鼓励开发人员使用自动将客户端输入绑定到代码变量和内部对象的函数。 攻击者可以使用这种方法来更新或覆盖开发人员从未打算公开的敏感对象的属性。
影响:
利用该漏洞可能会导致权限升级、数据篡改、绕过安全机制等。
API 是否容易受到攻击?
现代应用程序中的对象可能包含许多属性。 其中一些属性应由客户端直接更新(例如,user.first_name 或 user.address),而另一些则不应该(例如,user.is_vip 标志)。
如果 API 端点自动将客户端参数转换为内部对象属性,而不考虑这些属性的敏感性和暴露级别,则该端点容易受到攻击。 这可能允许攻击者更新他们不应访问的对象属性。
敏感属性的示例:
权限相关属性:user.is_admin、user.is_vip 只能由管理员设置。
与流程相关的属性:user.cash 只能在付款验证后在内部设置。
内部属性:article.created_time 只能由应用程序内部设置。
攻击场景示例
场景#1
乘车共享应用程序为用户提供了编辑其个人资料的基本信息的选项。 在此过程中,API 调用将使用以下合法 JSON 对象发送到 PUT /api/v1/users/me:
{“用户名”:“inons”,“年龄”:24}
请求 GET /api/v1/users/me 包含一个额外的credit_balance 属性:
{"user_name":"inons","age":24,"credit_balance":10}
攻击者使用以下有效负载重放第一个请求:
{“user_name”:“攻击者”,“年龄”:60,“credit_balance”:99999}
由于端点容易受到大规模分配的影响,攻击者无需付费即可获得积分。
场景#2
视频共享门户允许用户上传和下载不同格式的内容。 探索 API 的攻击者发现端点 GET /api/v1/videos/{video_id}/meta_data 返回带有视频属性的 JSON 对象。 其中一个属性是“mp4_conversion_params”:“-v codec h264”,这表示应用程序使用 shell 命令来转换视频。
攻击者还发现端点 POST /api/v1/videos/new 容易受到批量分配的影响,并允许客户端设置视频对象的任何属性。 攻击者设置恶意值如下:“mp4_conversion_params”:“-v codec h264 && format C:/”。 一旦攻击者将视频下载为 MP4,该值将导致 shell 命令注入。
攻击者利用批量分配漏洞:
当来自客户端的手动修改不可变内部对象属性的请求不受 API 端点限制时,就会出现 API 批量分配漏洞。
攻击者可以利用此漏洞,通过构建 HTTP 请求来升级用户权限、绕过安全机制或使用任何其他方法使 API 端点以非设计的方式工作。
注意:批量分配和过多数据暴露在 OWASP API Sec 2019 中是一个单独的风险类别,现在已合并到名为“损坏对象属性级别授权”的新风险类别中
如何预防
如果可能,请避免使用自动将客户端输入绑定到代码变量或内部对象的函数。
仅将应由客户端更新的属性列入白名单。
使用内置功能将客户端不应访问的属性列入黑名单。
如果适用,请显式定义并强制执行输入数据有效负载的架构。
增加反序列化配置
#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()
接口使用参数签名机制,如HMac, HMac Springboot, 微信支付参数签名
#前端请求
请求 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("签名异常");
}
}
Jackson类库解决方案
Solution - Jackson @JsonView
We can create JSON view like below:
public class View { public static class Editable {} public static class Viewable extends Editable {} public static class Internal extends Viewable {} }
Then annotate our mode class:
@JsonIgnoreProperties(ignoreUnknown = true) public class Model implements Serializable { @JsonView(View.Editable.class) protected String editableField; @JsonView(View.Viewable.class) protected String viewableField; @JsonView(View.Internal.class) protected String internalField; }
At last, we annotate out jax-rs resource with @JsonView annotation.
@GET @Produces(MediaType.APPLICATION_JSON ) @JsonView(View.Viewable.class) public Iterable<Model> search() {} @GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON ) @JsonView(View.Viewable.class) public Model getModel(@PathParam("id") final String id) {} @POST @Consumes({MediaType.APPLICATION_JSON}) public Response add(@JsonView(View.Editable.class) final Model model) {}
Spring MVC provides data binder that we can specify what fields are not allowed.
禁用字段:
@InitBinder public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields(DISALLOWED_FIELDS);
}
允许字段:
@Controller
public class UserController {
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.setAllowedFields(["userid", "password", "email"]);
}
...
}
External
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
- Testing for Mass Assignment
今天先到这儿,希望对云原生,技术领导力, 企业管理,系统架构设计与评估,团队管理, 项目管理, 产品管管,团队建设 有参考作用 , 您可能感兴趣的文章:
领导人怎样带领好团队
构建创业公司突击小团队
国际化环境下系统架构演化
微服务架构设计
视频直播平台的系统架构演化
微服务与Docker介绍
Docker与CI持续集成/CD
互联网电商购物车架构演变案例
互联网业务场景下消息队列架构
互联网高效研发团队管理演进之一
消息系统架构设计演进
互联网电商搜索架构演化之一
企业信息化与软件工程的迷思
企业项目化管理介绍
软件项目成功之要素
人际沟通风格介绍一
精益IT组织与分享式领导
学习型组织与企业
企业创新文化与等级观念
组织目标与个人目标
初创公司人才招聘与管理
人才公司环境与企业文化
企业文化、团队文化与知识共享
高效能的团队建设
项目管理沟通计划
构建高效的研发与自动化运维
某大型电商云平台实践
互联网数据库架构设计思路
IT基础架构规划方案一(网络系统规划)
餐饮行业解决方案之客户分析流程
餐饮行业解决方案之采购战略制定与实施流程
餐饮行业解决方案之业务设计流程
供应链需求调研CheckList
企业应用之性能实时度量系统演变
如有想了解更多软件设计与架构, 系统IT,企业信息化, 团队管理 资讯,请关注我的微信订阅号:
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。