中国知名网站排行榜,网页设计师的职业规划,英文设计网站,做网站的技术体系一、API成批分配漏洞介绍
批量分配#xff1a;在API的业务对象或数据结构中#xff0c;通常存在多个属性#xff0c;攻击者通过篡改属性值的方式#xff0c;达到攻击目的。比如通过设置user.is_admin和user.is_manager的值提升用户权限等级#xff1b;假设某API的默认接口…一、API成批分配漏洞介绍
批量分配在API的业务对象或数据结构中通常存在多个属性攻击者通过篡改属性值的方式达到攻击目的。比如通过设置user.is_admin和user.is_manager的值提升用户权限等级假设某API的默认接口调用参数为{user_name:useris_admin:0}而恶意攻击者修改请求参数提交值为{user_name:attackeris_admin:1}通过修改参数is_admin的值来提升为管理员权限。
应用程序中潜藏的安全漏洞是一种非常大的隐患攻击者会通过某一个安全漏洞窃取站点内的用户隐私等重要信息。在扫描应用程序时我们需要对多项内容进行配置。那么AppScan扫描应用程序需要URL吗是需要的。在新版的AppScan还可以扫除API成批分配的问题我们需要AppScan扫出API成批分配问题解决方案来解决。
APPScan 10.0.7新增的扫描功能 HCL AppScan® Enterprise 中的新增功能 (hcltechsw.com)增加了批量分配API的规则。
AppScan扫描应用程序需要URL吗
AppScan扫描应用程序是否需要URL那么我们就要看AppScan是如何扫描应用程序的。
1.启动扫描位置 图1主界面
这里我们使用的是AppScan 10.0.8版本启动软件后单击主界面中【web应用程序】便可启动扫描进程。
2.配置扫描 图2配置界面
在配置界面中第一项便是要求填写【URL和服务器】在图2中【从该URL开始扫描】位置输入目标URL即可。
3.完全扫描模式下输入URL 图3完全扫描
当我们启动【完全扫描】模式时在【探索】位置我们可以对【URL和服务器】进行配置配置方式和【扫描web应用程序】的配置方式一致。
4.web API
AppScan主界面中除了【web应用程序】和【完全配置】外还有【web API】web API的配置是不需要的填写URL的。 图4扫描web API
web API虽然无需填写URL但需要填写客户机和描述文件。 漏洞条件
1、接口类型为application/json 参数传值、form表单等类型暂未受影响。
2、请求json参数不是接收参数的javabean及其父类中的任意属性。
3、接口HTTP状态码为200
请求json参数不是接收参数的javabean及其父类中的任意属性。
意思就是我javaben里面没有这个参数你却传递过来了例如我只需要pageNum和pageSize 你还传了role:admin 那么这样就有可能导致致特权升级、数据篡改、绕过安全机制。
二、AppScan扫出API成批分配问题
可利用性
利用通常需要了解业务逻辑、对象关系和 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 {“user_name” : “inons”“age” : 24} 请求 GET /api/v1/users/me 包含一个额外的credit_balance 属性 {user_name : inons, age:24, credit_balance : 10} 攻击者使用以下有效负载重放第一个请求 {“user_name” : “攻击者”“age” : 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增加反序列化配置方案
1、反序列化所使用的框架的配置
jackson
如果SpringBoot使用的默认jackson做的序列化可以考虑对jackson配置来解决传冗余参的问题。
可以直接在配置文件中增加配置
spring:jackson:serialization:# 某些类对象无法序列化的时候是否报错fail_on_empty_beans: truedeserialization:# json对象中有不存在的属性时候是否报错fail_on_unknown_properties: true
或自建配置类
Configuration
public class JacksonConverters {Beanpublic HttpMessageConverters JacksonHttpMessageConverters() {MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter new MappingJackson2HttpMessageConverter();ObjectMapper objectMapper new ObjectMapper();//省略其他配置开始//反序列化的时候如果多了其他属性,抛出异常objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);//省略其他配置结束}}
fastjson
如果SpringBoot使用的是fastjson做的序列化在2.0.42版本中增加了解决方案可以考虑对fastjson配置来解决传冗余参的问题。
/*** author admin*/
Configuration
public class Fastjson2Config {/*** 使用fastJson解析*/Beanpublic HttpMessageConverters fastJsonHttpMessageConverters() {FastJsonHttpMessageConverter converter new FastJsonHttpMessageConverter();FastJsonConfig config new FastJsonConfig();/** API成批分配利用问题反序列化的时候如果多了其他属性修复方法* 第一json反序列化组件设置如fastjson与jackson* 第二签名验证** fastjson 2.0.42增加了ErrorOnUnknownProperties修复API成批分配利用问题反序列化的时候如果多了其他属性,抛出异常* https://github.com/alibaba/fastjson2/issues/1944** JSONObject jsonObject JSONObject.of(id, 123, name, xxx);* String str jsonObject.toJSONString();* assertEquals(jsonObject.getIntValue(id), JSON.parseObject(str, Bean.class).id);* assertThrows(JSONException.class, () - JSON.parseObject(str, Bean.class, JSONReader.Feature.ErrorOnUnknownProperties));* assertEquals(jsonObject.getIntValue(id), jsonObject.toJavaObject(Bean.class).id);* assertThrows(JSONException.class, () - jsonObject.toJavaObject(Bean.class, JSONReader.Feature.ErrorOnUnknownProperties));** jackson中可以加入* spring:* jackson:* deserialization:* fail-on-unknown-properties: true* 或* //反序列化的时候如果多了其他属性,抛出异常* objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);** 统一异常捕获或者返回处增加非200状态码**/config.setDateFormat(yyyy-MM-dd HH:mm:ss);config.setReaderFeatures(JSONReader.Feature.ErrorOnUnknownProperties);config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue, JSONWriter.Feature.PrettyFormat);converter.setDefaultCharset(StandardCharsets.UTF_8);ListMediaType supportedMediaTypes new ArrayList();supportedMediaTypes.add(MediaType.APPLICATION_JSON);converter.setFastJsonConfig(config);converter.setSupportedMediaTypes(supportedMediaTypes);return new HttpMessageConverters(converter);}}
2、统一异常捕获或者返回处增加非200状态码 /*** 捕获反序列化异常HttpMessageNotReadableException增加500状态码返回* param request 请求* param exception 异常对象* return 响应*/
ExceptionHandler(value HttpMessageNotReadableException.class)
public ResponseEntityMapString, Object methodHttpMessageNotReadableExceptionHandler(HttpServletRequest request, HttpMessageNotReadableException exception) {//按需重新封装需要返回的错误信息WebRequest webRequest new ServletWebRequest(request);MapString, 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);
}
或者在其他异常拦截方法上增加状态码注解 ResponseStatus()
方案二接口使用参数签名机制
如HMac, HMac Springboot, 微信支付参数签名
#前端请求
请求 URL: http://localhost/cars/query
请求方法: POST
HTTP状态码200
playload:{color:red,company:ltl,seats:2-2} #正常请求
HeadersignErOVBda4VMFdX9aixigRslAjY0rhT7lLxy
#后端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 IterableModel 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 {InitBinderpublic void initBinder(WebDataBinder binder, WebRequest request) {binder.setAllowedFields([userid, password, email]);}...}
四、总结
以上便是AppScan扫描应用程序需要URL吗AppScan扫出API成批分配问题解决方案的内容。AppScan扫描应用程序是需要URL的同时AppScan完全扫描也是需要URL的在新版的软件中只有web API模式是无需URL的。新版的AppScan可以扫出API成批分配的问题对于此类问题我们只需要执行反序列化配置方案便可拦截API成批分配的问题。更多有关AppScan使用技巧尽在AppScan中文网站