...
When the local system cannot be trusted, an explicit signature verification check must be built within the invoking program. This can be achieved by obtaining the chain of certificates from the CodeSource
of the class being loaded and checking if any one of the certificates belongs to the trusted signer whose certificate has been obtained securely beforehand and stored in a local keystore. The invokeClass
method can be modified to do this as shown in this compliant solution.
Code Block | ||
---|---|---|
| ||
public void invokeClass(String name, String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, GeneralSecurityException, IOException { Class c = loadClass(name); Certificate[] certs = c.getProtectionDomain().getCodeSource().getCertificates(); if(certs == null) { System.out.println("No signature!"); return; // return, do not execute if unsigned } KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(System.getProperty("user.home"+ File.separator + "keystore.jks")), "loadkeystorepassword".toCharArray()); Certificate pubCert = ks.getCertificate("user"); // user is the alias certs[0].verify(pubCert.getPublicKey()); // check with the trusted public key, else throws exception } |
(Note that invokeClass
now has two more exceptions in its throws
clause, so the catch
block in the main
method must be altered accordingly.)
It is not always the case that arbitrary code gets executed. By default, the URLClassLoader
and all its subclasses are only given enough permissions to interact with the URL
that was specified when the URLClassLoader
object was created. This means that the program can only interact with the specified host. However, this does not mitigate the risk completely as the loaded file may be granted appropriate privileges to perform more sensitive operations such as updating an existing local JAR file.
...