Avoid instantiating arbitrary classes

This PR avoids the use of `Class#newInstance`, which is
deprecated in Java 9.

In particular, previously you could set the `config.strategy`
system to an arbitrary class that would get instantiated even
if it was not a subclass of `ConfigLoadingStrategy`. This is
now checked before instantiating the class.

The previous behavior could arguably be considered a security
concern when an attacker has write access to system properties,
though in such a scenario there are likely many other ways to
load arbitrary code.
This commit is contained in:
Arnout Engelen 2022-02-01 14:29:45 +01:00
parent 80725b89ea
commit fe85a7d9e7
No known key found for this signature in database
GPG Key ID: 061107B0F74A6DAA
2 changed files with 10 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import com.typesafe.config.impl.Parseable;
import java.io.File;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
@ -1241,7 +1242,11 @@ public final class ConfigFactory {
if (className != null) {
try {
return ConfigLoadingStrategy.class.cast(Class.forName(className).newInstance());
return Class.forName(className).asSubclass(ConfigLoadingStrategy.class).getDeclaredConstructor().newInstance();
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause == null) throw new ConfigException.BugOrBroken("Failed to load strategy: " + className, e);
else throw new ConfigException.BugOrBroken("Failed to load strategy: " + className, cause);
} catch (Throwable e) {
throw new ConfigException.BugOrBroken("Failed to load strategy: " + className, e);
}

View File

@ -106,7 +106,7 @@ public class ConfigBeanImpl {
}
// Fill in the bean instance
T bean = clazz.newInstance();
T bean = clazz.getDeclaredConstructor().newInstance();
for (PropertyDescriptor beanProp : beanProps) {
Method setter = beanProp.getWriteMethod();
Type parameterType = setter.getGenericParameterTypes()[0];
@ -125,8 +125,10 @@ public class ConfigBeanImpl {
setter.invoke(bean, unwrapped);
}
return bean;
} catch (InstantiationException e) {
} catch (NoSuchMethodException e) {
throw new ConfigException.BadBean(clazz.getName() + " needs a public no-args constructor to be used as a bean", e);
} catch (InstantiationException e) {
throw new ConfigException.BadBean(clazz.getName() + " needs to be instantiable to be used as a bean", e);
} catch (IllegalAccessException e) {
throw new ConfigException.BadBean(clazz.getName() + " getters and setters are not accessible, they must be for use as a bean", e);
} catch (InvocationTargetException e) {