前言
一个朋友问我他在springboot Eureka的xstream漏洞的条件下,使用Powercat这个powershell工具反弹windows的shell失败了,问我有没有解决方案。我看到这个问题的第一反应就是,xstream为何不打内存马呢。首先搜索了网上的exp和利用工具,都是通过ProcessBuilder执行命令的。这种做法其实在实战中不妥,因为springboot无法植入文件webshell。要想命令得到回显,要么反弹shell,要么上线c2。前者容易被检测到,后者需要考虑文件下载免杀的问题。都不是非常成熟。实战中,内存马才是王道!
公开poc尝试
首先贴一个网上公开poc
1 | #!/usr/bin/env python |
看了这个poc后,我下意识觉得就是一个普通的xstream反序列化,拿起以前的payload就要给站打了(https://xz.aliyun.com/t/10619)。结果发现别说内存马了,普通cmd命令都执行不了。中间出现了问题,于是我自己搭建了一个Springboot-Eureka漏洞的环境(https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-eureka-xstream-rce)进行调试。
仔细分析
首先找到了触发点,com.netflix.discovery.converters.wrappers.CodecWrappers.decode(InputStream inputStream, Class<T> type)
往里跟一步,发现这个点和通常遇到的xstream.fromXML(String)不同,其多设置了一个root,root的值为eureka-client.jar中的一个类
再不断的往里面跟,一直到下图这一步,发现了问题,HashMap类型的转换器被转化为了com.netflix.discovery.converters.Converters$MetadataConverter
下图是我搭建的xstream.fromXML(String)这种类型的反序列化场景,可以看到正常情况下,HashMap类型的转换器是com.thoughtworks.xstream.converters.collections.MapConverter类型
因为转换器变了,因此我们的xstream反序列化payload失效了。
这时候转过头来看一下网上的poc为何生效,首先判断一下网上poc是哪个版本xstream爆出来的漏洞。我发现CVE-2020-26217是和exp版本最贴近的
exp所修改的部分就是把
1 | <map> |
改成了
1 | <linked-hash-set> |
和我们之前发现的问题对上了,Map这个标签不能在exp出现,会导致exp失效,网上exp的解决办法是把Map换成了linked-hash-set。
这里提一嘴,不止Map标签不能用,例如:http://x-stream.github.io/CVE-2021-29505.html这个CVE,以反序列化标签作为开头的方式也是不能用的,具体原因大家自己debug下,不浪费篇幅了,主要是告诉大家这里的xstream比较特殊,要注意坑。
柳暗花明
试了很多个poc之后,发现很多都不能直接用,突然想到,为何不直接在网上exp基础上,修改进行内存马注入呢?
观察exp,发现本质就是调用了ProcessBuilder的start方法
搭建环境进行debug,发现就是一个可以控制对象的属性,然后调用其任意的无参方法的触发点。
需要调用无参方法进行任意java代码执行,一下就想到了com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
把之前的exp的ProcessBuilder部分改成如下即可