CWE-470: Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')
Learn about CWE-470 (Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')), its security impact, exploitation methods, and prevention guidelines.
What is Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')?
• Overview: This vulnerability occurs when an application uses external input to determine which classes or code to use through reflection, without adequately validating the input. This can allow attackers to invoke unintended classes or methods, leading to unauthorized control over the program's behavior.
• Exploitation Methods:
- Attackers can manipulate input to select and execute unexpected classes or methods.
- Common techniques include supplying crafted input that points to malicious or unintended code, potentially bypassing security checks.
• Security Impact:
- Direct consequences include execution of unauthorized or harmful code.
- Potential cascading effects involve bypassing authentication, access control, or introducing new vulnerabilities.
- Business impact can range from data breaches to service disruption and reputational damage.
• Prevention Guidelines:
- Specific code-level fixes include validating and sanitizing all external inputs before using them in reflection.
- Security best practices involve implementing strict input validation and using whitelists for allowed classes or methods.
- Recommended tools and frameworks include security libraries that enforce safe reflection practices and static analysis tools to detect unsafe reflection usage.
Technical Details
Likelihood of Exploit: Not specified
Affected Languages: Java, PHP, Interpreted
Affected Technologies: Not specified
Vulnerable Code Example
Java Example
import java.lang.reflect.Constructor;
public class ReflectionExample {
public Object createInstance(String className) throws Exception {
// Vulnerable: Directly using user input to determine the class to instantiate
Class<?> clazz = Class.forName(className); // Unsafe use of reflection
Constructor<?> constructor = clazz.getConstructor();
return constructor.newInstance(); // Instantiates the class
}
public static void main(String[] args) {
ReflectionExample example = new ReflectionExample();
try {
// Simulate external input
Object obj = example.createInstance(args[0]); // Potentially dangerous input
System.out.println("Created instance of: " + obj.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Explanation:
- Direct Reflection Use: The code takes a class name as input and directly uses Java reflection to instantiate the class. This is dangerous because it allows instantiation of any class, including those that could be harmful.
- Security Risk: A malicious user could pass any class name, potentially creating instances of classes that perform unauthorized actions or disrupt the application.
How to fix Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection')?
To fix this vulnerability, you should:
- Whitelist Valid Classes: Restrict the classes that can be instantiated by maintaining a list of allowed classes.
- Validate Input: Ensure that the input matches the expected class names.
- Avoid Direct Reflection Based on User Input: Instead of using reflection directly on user input, map input values to known safe classes.
Fixed Code Example
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class SafeReflectionExample {
// Whitelist of allowed classes mapped by a safe identifier
private static final Map<String, Class<?>> ALLOWED_CLASSES = new HashMap<>();
static {
ALLOWED_CLASSES.put("safeClass1", com.example.SafeClass1.class);
ALLOWED_CLASSES.put("safeClass2", com.example.SafeClass2.class);
// Add more allowed classes as needed
}
public Object createInstance(String classIdentifier) throws Exception {
// Validate and map input to a known safe class
Class<?> clazz = ALLOWED_CLASSES.get(classIdentifier); // Retrieve class from whitelist
if (clazz == null) {
throw new IllegalArgumentException("Invalid class identifier"); // Handle invalid input
}
Constructor<?> constructor = clazz.getConstructor();
return constructor.newInstance(); // Safely instantiate the class
}
public static void main(String[] args) {
SafeReflectionExample example = new SafeReflectionExample();
try {
// Safely handle input
Object obj = example.createInstance(args[0]);
System.out.println("Created instance of: " + obj.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Explanation:
- Whitelist Implementation: A
Map<String, Class<?>>
is used to maintain a whitelist of allowed classes, ensuring that only known and safe classes are instantiated. - Input Validation: The input is validated against this map, and any invalid input is handled appropriately by throwing an exception.
- Safe Reflection: By using a whitelist, the risk of instantiating unauthorized classes is eliminated, enhancing security.