ysoserial payloads/JRMPListener
payloads/JRMPListener
JRMPListener的攻击流程:
1.生成payloads/JRMPListener发送给服务器,当服务器反序列化payloads/JRMPListener后,即会开启一个端口进行监听。
2.使用exploit/JRMPClient模块发送payload,服务器就会把payload进行反序列化,从而完成进行攻击。
直接通过ysoserial源码调试JRMPListener类来理解payloads/JRMP模块的利用原理
生成Payload
打开idea,设置启动参数,主类为ysoserial.GeneratePayload,参数为JRMPListener 1199
 
断点启动,GeneratePayload类中调用了JRMPListener的getObject方法
 
跟进JRMPListener#getObject
 
第一行jrmpPort获取了端口号1199
重点讲一下第二部分
 
46行new了一个UnicastServerRef对象并且把jrmpPort端口号传入了进去
然后调用了一个Reflections工具类构造了UnicastRemoteObject对象
Reflections构造对象
在前面调用了Reflections#createWithConstructor方法,利用ActivationGroupImpl.class、RemoteObject.class、RemoteRef.class、UnicastServerRef构造了一个对象
 
现在转到工具类Reflections.java
 
debug来解释下这个工具类的作用
1.获取有参构造方法
在这里获取了RemoteObject类的有参构造,参数为RemoteRef.class

2.暴力反射
setAccessible(objCons);
3.获得Constructor
在这里用了ReflectionFactory.newConstructorForSerialization来创建无参构造方法
下面用一个简单的demo来解释下这段代码的作用
ReflectionFactory.getReflectionFactory().newConstructorForSerialization()
新建一个Person类,创建其有参和无参构造方法
public class Person{
    private String name;
    public Person() {
        System.out.println("Person无参构造方法");
    }
    public Person(String name) {
        this.name = name;
        System.out.println("调用有参构造" + name.toString());
    }
}
新建一个User类,继承Person
public class User extends Person{
    public void eat(){
        System.out.println("eat...");
    }
}
新建Test类
public class Test1 {
    public static void main(String[] args) throws Exception {
        //获得Person的有参构造函数
        Constructor<Person> personConst = Person.class.getDeclaredConstructor(String.class);
        //获得Person的Constructor对象
        Constructor constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(
                User.class,
            	personConst
        );
        //constructor.setAccessible(true);
        //实例化对象,给person构造方法传入xxx,并转型成User
        User user = (User) constructor.newInstance("xxx");
        user.eat();
    }
}
运行结果:
调用有参构造xxx
eat...
可以看到,虽然User类没有构造方法,但是依然能通过父类创建出来,并且调用其方法。
demo解读
解释下在这里newConstructorForSerialization()传入的参数
第一个参数是需要创建对象的Class,比如User.class
第二个参数是对象的父类的构造方法,比如Person.class.getDeclaredConstructor()或者Person.class.getDeclaredConstructor(String.class)
因为不能确定一个类中是否有无构造函数,所以在这里yososeroal中利用ReflectionFactory.newConstructorForSerialization创建对象的话,比直接反射创建对象适用性要高,并不会产生报错。
继续回到ysoserial源码中,就看的很明白了
ReflectionFactory.getReflectionFactory()获取了ReflectionFactory对象的实例
 
之后进行了newConstructorForSerialization()
传入的第一个值是ActivationGroupImpl.class,第二个则是它的父类RemoteObject的构造方法。以下是ActivationGroupImpl的继承关系图
 
4.创建出ActivationGroupImpl对象
最后一行把获取到的Constructor进行了newInstance,并且传入了consArgs,即UnicastServerRef对象
 
UnicastServerRef对象通过父类有参构造函数,赋值给了ref
 
然后对其向下转型成了ActivationGroupImpl类(T即为ActivationGroupImpl)
 
最后返回值就是一个ActivationGroupImpl对象了
回到JRMPListener.java,此时的uro为ActivationGroupImpl

跟进49行,这里又调用了Reflections类得getField方法,把UnicastRemoteObject中的port值设置成了jrmpPort,也就是1199。
最后返回的payload对象就是ActivationGroupImpl
然后在GeneratePayload中把ActivationGroupImpl进行了序列化操作

gadget链分析
以下是ysoserial给出给出得gadget链
* Gadget chain:
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235
* UnicastRemoteObject.reexport() line: 266
* UnicastRemoteObject.exportObject(Remote, int) line: 320
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
* LiveRef.exportObject(Target) line: 147
* TCPEndpoint.exportObject(Target) line: 411
* TCPTransport.exportObject(Target) line: 249
* TCPTransport.listen() line: 319
在前面生成payload得时候返回的是ActivationGroupImpl对象,但是其对象本身是没有readObject方法的,所以从父类找readObject最终找到UnicastRemoteObject
攻击流程:
payload发送给服务器,服务器会对其进行反序列化,触发UnicastRemoteObject#readObject
 
进入reexport
 
这里执行了exportObject,传入了ActivationGroupImpl对象和port
继续跟进到UnicastServerRef#exportObject,这里后面就是之前分析RMI时候操作了。
 
在this.ref.exportObject执行后会最终到TCPTransport类的exportObject方法
 
跟进listen
 
调用TCPEndpoint#newServerSocket方法,会开启端口监听
 
如果服务器反序列化了该payload,就会开启一个监听。
这里就做了一个很简单的调试,更具体的可以看我之前写的文章,RMI源码调试
参考链接:

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号