最近几周一直在研究java的反序列化漏洞相关问题 我们先来看看这个著名的类和其中的那个方法了
对没错 就是这个大名鼎鼎的readObject方法 一旦黑客发现了"可乘之机" 就会构造一个paylaods比如这个
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
ProcessBuilder processBuilder = new ProcessBuilder("whoami");
Process process = processBuilder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
StringBuilder out = new StringBuilder();
while ((line = br.readLine()) != null) {
out.append(line);
}
System.out.println(out);
}
当然这个paylaods只是执行了whoami这个系统命令 如果是其他的指令 那可就不好玩了
实际任何一个反序列化漏洞的构成都是如此 反序列化漏洞的paylaods里面重写了readObject方法
我对readObjectStream的类进行了改写注意注释就是改写的地方
private ObjectStreamClass readNonProxyDesc(boolean unshared)
throws IOException
{
if (bin.readByte() != TC_CLASSDESC) {
throw new InternalError();
}
ObjectStreamClass desc = new ObjectStreamClass();
int descHandle = handles.assign(unshared ? unsharedMarker : desc);
passHandle = NULL_HANDLE;
ObjectStreamClass readDesc = null;
try {
readDesc = readClassDescriptor();
} catch (ClassNotFoundException ex) {
throw (IOException) new InvalidClassException(
"failed to read class descriptor").initCause(ex);
}
Class<?> cl = null;
ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true);
final boolean checksRequired = isCustomSubclass();
try {
if ((cl = resolveClass(readDesc)) == null) {
resolveEx = new ClassNotFoundException("null class");
} else if (checksRequired) {
ReflectUtil.checkPackageAccess(cl);
}
} catch (ClassNotFoundException ex) {
resolveEx = ex;
}
//--------------
System.out.println(cl);
Method []m=((Class)cl).getDeclaredMethods();
for(Method ms:m){
System.out.println(ms);
if(ms.toString().contains(".readObject(")){
System.out.println("HACK!");
return null;
}
}
//--------------
skipCustomData();
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
handles.finish(descHandle);
passHandle = descHandle;
return desc;
}