最近查看到jackson反序列化漏洞的问题,网上查了查资料,这里记录一下
1. DefaultTyping类型
public static enum DefaultTyping {
JAVA_LANG_OBJECT,
OBJECT_AND_NON_CONCRETE,
NON_CONCRETE_AND_ARRAYS,
NON_FINAL,
EVERYTHING;
private DefaultTyping() {
}
}
DefaultTyping有四个选项:
JAVA_LANG_OBJECT: 当对象属性类型为Object时生效;
OBJECT_AND_NON_CONCRETE: 当对象属性类型为Object或者非具体类型(抽象类和接口)时生效;
NON_CONCRETE_AND+_ARRAYS: 同上, 另外所有的数组元素的类型都是非具体类型或者对象类型;
NON_FINAL: 对所有非final类型或者非final类型元素的数组。
因此,当开启DefaultTyping后,会开发者在反序列化时指定要还原的类,过程中调用其构造方法setter方法或某些特殊的getter方法,当这些方法中存在一些危险操作时就造成了代码执行。
2. 反序列化漏洞说明
上面提到了NON_FINAL ,这里再说一下关于它的反序列化漏洞:
NON_FINAL ,包含即将被序列化的类里的全部、非final的属性,也就是相当于整个类、除final外的的属性信息都需要被序列化和反序列化。
enableDefaultTyping的NON_FINAL这个功能涉及到java著名的反序列化漏洞。各位系统之间调用数据的项目还是慎重使用.
漏洞详情
我们的服务器数据都是通过安全认证进行存储的,所以这里不存在这个漏洞。
如果数据能够让用户自己数据和存储,大家就要注意这个漏洞了!!!
2.1 漏洞描述
近日,云安全团队跟踪到jackson-databind在github上更新了一个新的反序列化利用类com.caucho.config.types.ResourceRef,issue编号2660,该类绕过了之前jackson-databind维护的黑名单类。如果项目中包含resin-kernel库,并且JDK版本较低的话,请及时升级jackson-databind到安全版本。
2.2. 影响范围
jackson-databind < 2.9.10.4
JDK < 6u201、7u191、8u182、11.0.1(LDAP)
2.3 漏洞分析
该漏洞本质是java的JNDI注入,我们先来了解下JNDI基础知识。简单来说,JNDI是一组应用程序接口,它为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定位用户、网络、机器、对象和服务等各种资源。比如可以利用JNDI在局域网上定位一台打印机,也可以用JNDI来定位数据库服务或一个远程Java对象。JNDI底层支持RMI远程对象,RMI注册的服务可以通过JNDI接口来访问和调用。JNDI接口在初始化时,可以将RMI URL作为参数传入,而JNDI注入就出现在客户端的lookup()函数中,如果lookup()的参数可控就可能被攻击。
因此分析的时候,可以直接先搜索受影响类的lookup方法,看看漏洞入口在哪里,本文复现的时候用的是resin-kernel-4.0.52版本。
参考:https://anquan.baidu.com/article/1069
Jackson原生框架是没有存在直接漏洞利用的类的,我们需要引入一些外部类去构造Gadget
CVE-2020-8840
这个CVE利用xbean-reflect
利用链造成JNDI注入
影响版本:2.0.0 - 2.9.10.2
poc:
| |
跟一下流程:
调用mapper.readValue()的时候,return _readMapAndClose
步入_readMapAndClose
,经过读取json,配置DeserializationContext
最终到else分支
调用了deser.deserialize(p, ctxt)
继续Step Into,直到跟到com/fasterxml/jackson/databind/deser/BeanDeserializer.class#deserialize
到这里也就是之前熟悉的Jackson反序列化流程了,继续步入到com/fasterxml/jackson/databind/deser/BeanDeserializer.class
通过setter.invoke()执行方法,步入eval类org/apache/xbean/propertyeditor/JndiConverter.class
进行lookup(), 造成JNDI注入
完整调用链
6 解决反序列化漏洞的方法
官方在github的更新措施(https://github.com/FasterXML/jackson-databind/commit/1645efbd392989cf015f459a91c999e59c921b15),
仍然是添加com.caucho.config.types.ResourceRef为黑名单类,但这种方式治标不治本,后续可能出现其他绕过黑名单的gdaget。
6.1 黑名单类:
或者:
Set<String> s = new HashSet<String>();
// Courtesy of [https://github.com/kantega/notsoserial]:
// (and wrt [databind#1599])
s.add("org.apache.commons.collections.functors.InvokerTransformer");
s.add("org.apache.commons.collections.functors.InstantiateTransformer");
s.add("org.apache.commons.collections4.functors.InvokerTransformer");
s.add("org.apache.commons.collections4.functors.InstantiateTransformer");
s.add("org.codehaus.groovy.runtime.ConvertedClosure");
s.add("org.codehaus.groovy.runtime.MethodClosure");
s.add("org.springframework.beans.factory.ObjectFactory");
s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
s.add("org.apache.xalan.xsltc.trax.TemplatesImpl");
// [databind#1680]: may or may not be problem, take no chance
s.add("com.sun.rowset.JdbcRowSetImpl");
// [databind#1737]; JDK provided
s.add("java.util.logging.FileHandler");
s.add("java.rmi.server.UnicastRemoteObject");
// [databind#1737]; 3rd party
//s.add("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor"); // deprecated by [databind#1855]
s.add("org.springframework.beans.factory.config.PropertyPathFactoryBean");
// s.add("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); // deprecated by [databind#1931]
// s.add("com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"); // - "" -
// [databind#1855]: more 3rd party
s.add("org.apache.tomcat.dbcp.dbcp2.BasicDataSource");
s.add("com.sun.org.apache.bcel.internal.util.ClassLoader");
// [databind#1899]: more 3rd party
s.add("org.hibernate.jmx.StatisticsService");
s.add("org.apache.ibatis.datasource.jndi.JndiDataSourceFactory");
// [databind#2032]: more 3rd party; data exfiltration via xml parsed ext entities
s.add("org.apache.ibatis.parsing.XPathParser");
// [databind#2052]: Jodd-db, with jndi/ldap lookup
s.add("jodd.db.connection.DataSourceConnectionProvider");
// [databind#2058]: Oracle JDBC driver, with jndi/ldap lookup
s.add("oracle.jdbc.connector.OracleManagedConnectionFactory");
s.add("oracle.jdbc.rowset.OracleJDBCRowSet");
// [databind#2097]: some 3rd party, one JDK-bundled
s.add("org.slf4j.ext.EventData");
s.add("flex.messaging.util.concurrent.AsynchBeansWorkManagerExecutor");
s.add("com.sun.deploy.security.ruleset.DRSHelper");
s.add("org.apache.axis2.jaxws.spi.handler.HandlerResolverImpl");
// [databind#2186]: yet more 3rd party gadgets
s.add("org.jboss.util.propertyeditor.DocumentEditor");
s.add("org.apache.openjpa.ee.RegistryManagedRuntime");
s.add("org.apache.openjpa.ee.JNDIManagedRuntime");
s.add("org.apache.axis2.transport.jms.JMSOutTransportInfo");
// [databind#2326] (2.9.9)
s.add("com.mysql.cj.jdbc.admin.MiniAdmin");
// [databind#2334]: logback-core (2.9.9.1)
s.add("ch.qos.logback.core.db.DriverManagerConnectionSource");
// [databind#2341]: jdom/jdom2 (2.9.9.1)
s.add("org.jdom.transform.XSLTransformer");
s.add("org.jdom2.transform.XSLTransformer");
// [databind#2387]: EHCache
s.add("net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup");
// [databind#2389]: logback/jndi
s.add("ch.qos.logback.core.db.JNDIConnectionSource");
6.2 配置CacheManger
网上发现了一个更优雅的解决方案分享给大家。没有实际用过,只供参考
只需要在配置文件中配置一下CacheManger,使用jackson的一个带泛型的序列化工具实现。
/**
* spring cache 注解相关序列化操作
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
// 键序列化方式 redis字符串序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
// 值序列化方式 简单json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();
}
6.3 其他防御措施
1. 及时将jackson-databind升级到安全版本(>=2.9.10.4,> 2.10.0);
2. 升级到较高版本的JDK。
7. 参考:
https://www.leadroyal.cn/?p=594
http://www.lmxspace.com/2019/07/30/Jackson-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%B1%87%E6%80%BB/