常见的代码安全问题和安全规范

十年热恋 提交于 2021-01-04 15:00:09

一、json反序列化问题

参照这篇文章:https://www.freebuf.com/articles/web/258827.html

其实@RequestBody底层是jackson,程序员往往用@RequestBody处理fastjson的JSONObject,以方便快速解析json   (起码我们公司是这样)

对应的postman的请求截图:

这种方式是没有反序列化漏洞的(编写文章时的版本为springboot2.4),但是安全人员最担心的是使用fastjson的

com.alibaba.fastjson.JSON.parse  
com.alibaba.fastjson.JSON.parseObject

两个函数处理json串的时候因为黑名单和白名单的编写不规范导致的安全风险

在openrasp1.3.6中覆盖了fastjson以上两个函数和jackson的一系列解析函数,所以不用过于担心反序列化安全问题

 

接下来我们讨论一下反序列化的安全编码规范

1)jackson的安全编码:

1)禁用enableDefaultTyping
2)禁用JsonTypeInfo
3)使用activateDefaultTyping + 白名单过滤器(白名单中的类禁止包含readObject函数)

其中activateDefaultTyping的安全编码举例如下:

ObjectMapper om = new ObjectMapper();
BasicPolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()
                // 信任 com.hyit. 包下的类
                .allowIfBaseType("com.hyit.")
                .allowIfSubType("com.hyit.")
                // 信任 Collection、Map 等数据结构
                .allowIfSubType(Collection.class)
                .allowIfSubType(Number.class)
                .allowIfSubType(Map.class)
                .allowIfSubType(Temporal.class)
                .allowIfSubTypeIsArray()
                .build();
om.activateDefaultTyping(validator,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

如果某些场景,例如需要序列化、反序列化到redis数据库时
1.只能使用activateDefaultTyping函数,并且必须白名单校验
2.所有加入到白名单中的类不能包含readObject函数

2)fastjson的安全编码:

一、添加autotype白名单,添加白名单有三种方式
1. 在代码中配置
    ParserConfig.getGlobalInstance().addAccept("com.taobao.pac.client.sdk.dataobject."); 
    如果有多个包名前缀,分多次addAccept
2. 加上JVM启动参数
    -Dfastjson.parser.autoTypeAccept=com.taobao.pac.client.sdk.dataobject.,com.cainiao. 
    //如果有多个包名前缀,用逗号隔开
3. 通过fastjson.properties文件配置。
    支持通过类路径的fastjson.properties文件来配置,配置方式如下:
    fastjson.parser.autoTypeAccept=com.taobao.pac.client.sdk.dataobject.,com.cainiao. 
    // 如果有多个包名前缀,用逗号隔开safeMode模式

二、safeMode打开后,完全禁用autoType。
1. 在代码中配置
    ParserConfig.getGlobalInstance().setSafeMode(true);
    如果使用new ParserConfig的方式,需要注意单例处理,否则会导致低性能full gc

2. 加上JVM启动参数
    -Dfastjson.parser.safeMode=true

3. 通过fastjson.properties文件配置。
    通过类路径的fastjson.properties文件来配置,配置方式如下:
    fastjson.parser.safeMode=true

不论是jackson还是fastjson需要将数据按照以下方式与redis存取的时候,都必须使用白名单严格限制哪些类能被序列化和反序列化

jackson的例子
["java.util.ArrayList",[{"@class":"com.model.app","id":72,"uuid":"c4d7fc52-4096-4c79-81ef-32cb1b87fd28","type":2}]]
fastjson的例子
{"@type":"com.what21.fastjson.fj03.Group","id":"manager","name":"小奋斗教程","userList":[]}

1)jdk的选择 jdk使用1.8u271或以上版本 jdk使用11.09或以上版本

    以上版本已经解决已知的安全校验被绕过的问题

    以上版本默认可以缓解rmi或ldap协议被反序列化攻击的风险

2)常见高危组件的选用

    fastjson 1.2.75或以上版本,参照前文的代码规范

    jackson  2.10.x或以上版本,参照前文的代码规范

 

二、如何限制敏感字段直接进行json转换

使用@JsonIgnore

public class user {
    public int id;
    public String name;

    @JsonIgnore
    public String password;
}

比如user表,在password这个属性上添加@JsonIgnore,就会set和get方法都不会出现password,也就是这个属性不会被格式化

注解get上,就会发现前端不会显示password的数据,而注解在set上,后端就拿不到前端传过来的password的数据

对应的也可以直接使用@JsonIgnoreProperties作用在类上

@JsonIgnoreProperties({ "password" })
public class user {
    public int id;
    public String name;
    public String password;
}

或者扩展 BaseCommandController 的 Spring 应用程序可以替代  initBinder(HttpServletRequest request, ServletRequestDataBinder binder) 方法

以此获取对 Spring 模型绑定器的引用

@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {     
    binder.setDisallowedFields(new String[]{"details.role", "details.age", "password"}); 
}

这个方法的本质是修改WebDataBinder的setDisallowedFields字段的内容

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!