欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Java RMI远程反序列化任意类及远程代码执行解析(CVE-2017-3241

来源: 作者: 时间:2019-02-24 19:29 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助

本打算慢慢写出来的,但前几天发现国外有研究员发了一篇关于这个CVE的文章,他和我找到的地方很相似。然而不知道是不是Oracle认为是同一个漏洞然后合并了CVE,还是说我找错了CVE。
总之,先简单描述一下漏洞:对于任何一个以对象为参数的RMI接口,你都可以发一个自己构建的对象,迫使服务器端将这个对象按任何一个存在于class path中的可序列化类来反序列化。听起来可能有点绕,请往下看。
就直接上问题代码了。在Java RMI的sun.rmi.server.UnicastRef类中,有如下一段代码:
300    protected static Object More ...unmarshalValue(Class type, ObjectInput in)
301        throws IOException, ClassNotFoundException
302    {
303        if (type.isPrimitive()) {
304            if (type == int.class) {
305                return Integer.valueOf(in.readInt());
306            } else if (type == boolean.class) {
307                return Boolean.valueOf(in.readBoolean());
308            } else if (type == byte.class) {
309                return Byte.valueOf(in.readByte());
310            } else if (type == char.class) {
311                return Character.valueOf(in.readChar());
312            } else if (type == short.class) {
313                return Short.valueOf(in.readShort());
314            } else if (type == long.class) {
315                return Long.valueOf(in.readLong());
316            } else if (type == float.class) {
317                return Float.valueOf(in.readFloat());
318            } else if (type == double.class) {
319                return Double.valueOf(in.readDouble());
320            } else {
321                throw new Error("Unrecognized primitive type: " + type);
322            }
323        } else {
324            return in.readObject();
325        }
326    }
看324行,如果你熟悉java反序列化漏洞,看到此你应该就可以激动了。该代码直接调用readObject,且在原生Java类里。结合2016 black hat上那个spring-tx.jar或者之前apache common中的类,都可以实现远程代码执行。spring-tx里的那个我实验成功了,且Spring rmi中继承了这个漏洞。但Spring team表示不修,和他们没关系。。。
其实写到这,很多技术大牛已经可以自己找出怎么黑了。下面只是简单写写我如何通过正常Java RMI程序来攻击的,因为我觉得这招还是比较淫荡的。
以下是一个正常的服务器端接口,接口参数为Message对象,Message对象是要被序列化的对象:
public interface Services extends java.rmi.Remote
{
    String sendMessage(Message msg) throws RemoteException;
}
public class Message implements Serializable {
    private String msg;
    public Message()
    {
    }
   
    public String getMessage() {
        System.out.println("Processing message: "+msg);
        return msg;
    }
    public void setMessage(String msg) {
        this.msg = msg;
    }
    /*
     * server will tell the serialVersionUID for first run, then just put it below
     */
    private final static long serialVersionUID = 1311618551071721443L;
}
服务器端程序,sendMessage接口实现只是调用getMessage打印字符串:
public class RMIServer
   implements Services {
   public RMIServer() throws RemoteException {
   }

[1] [2] [3] [4] [5]  下一页

本打算慢慢写出来的,但前几天发现国外有研究员发了一篇关于这个CVE的文章,他和我找到的地方很相似。然而不知道是不是Oracle认为是同一个漏洞然后合并了CVE,还是说我找错了CVE。
总之,先简单描述一下漏洞:对于任何一个以对象为参数的RMI接口,你都可以发一个自己构建的对象,迫使服务器端将这个对象按任何一个存在于class path中的可序列化类来反序列化。听起来可能有点绕,请往下看。
就直接上问题代码了。在Java RMI的sun.rmi.server.UnicastRef类中,有如下一段代码:
300    protected static Object More ...unmarshalValue(Class type, ObjectInput in)
301        throws IOException, ClassNotFoundException
302    {
303        if (type.isPrimitive()) {
304            if (type == int.class) {
305                return Integer.valueOf(in.readInt()); 无奈人生安全网
306            } else if (type == boolean.class) {
307                return Boolean.valueOf(in.readBoolean());
308            } else if (type == byte.class) {
309                return Byte.valueOf(in.readByte());
310            } else if (type == char.class) {
311                return Character.valueOf(in.readChar());
312            } else if (type == short.class) {
313                return Short.valueOf(in.readShort());
314            } else if (type == long.class) {

copyright 无奈人生

315                return Long.valueOf(in.readLong());
316            } else if (type == float.class) {
317                return Float.valueOf(in.readFloat());
318            } else if (type == double.class) {
319                return Double.valueOf(in.readDouble());
320            } else {
321                throw new Error("Unrecognized primitive type: " + type);
322            }
323        } else {
324            return in.readObject(); 内容来自无奈安全网
325        }
326    }
看324行,如果你熟悉java反序列化漏洞,看到此你应该就可以激动了。该代码直接调用readObject,且在原生Java类里。结合2016 black hat上那个spring-tx.jar或者之前apache common中的类,都可以实现远程代码执行。spring-tx里的那个我实验成功了,且Spring rmi中继承了这个漏洞。但Spring team表示不修,和他们没关系。。。
其实写到这,很多技术大牛已经可以自己找出怎么黑了。下面只是简单写写我如何通过正常Java RMI程序来攻击的,因为我觉得这招还是比较淫荡的。
以下是一个正常的服务器端接口,接口参数为Message对象,Message对象是要被序列化的对象:
public interface Services extends java.rmi.Remote
{
    String sendMessage(Message msg) throws RemoteException;
}
public class Message implements Serializable {
    private String msg;
    public Message()
    {
    }
   
    public String getMessage() {

内容来自无奈安全网


        System.out.println("Processing message: "+msg);
        return msg;
    }
    public void setMessage(String msg) {
        this.msg = msg;
    }
    /*
     * server will tell the serialVersionUID for first run, then just put it below
     */
    private final static long serialVersionUID = 1311618551071721443L;
}
服务器端程序,sendMessage接口实现只是调用getMessage打印字符串:
public class RMIServer
   implements Services {
   public RMIServer() throws RemoteException {
   }
无奈人生安全网

[1] [2] [3] [4] [5]  下一页 www.wnhack.com

。 (责任编辑:admin)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。