Code should only be signed because it requires elevated privileges to perform some tasks. See rule ENV00-J. Do not sign code that performs only unprivileged operations for more information.
For example, applets are denied the privilege of making HTTP connections to any hosts except the host from which they came. But if When an applet requires an HTTP connection with an external host to download plugins plug-ins or extensions, its vendor may provide signed code rather than forcing the user to arbitrarily assign it the permissions it requires. Because executing privilege-elevated signed code can be extremely dangerous, verifying the authenticity of its origin is of utmost importance.
Java-based technologies typically use the Java Archive (JAR) feature for packaging files to facilitate platform to package files for platform-independent deployment. JAR files are the preferred means of distribution for Enterprise Java-Beans (EJB), MIDlets (J2ME), and Weblogic Server J2EE applications, for example. The point-and-click installation provided by Java Web Start also relies on the JAR file format for packaging. Vendors sign their JAR files when required. This certifies the authenticity of the code, but it cannot guarantee the security of the code.
...
Client code may lack programmatic checks of code signatures. For example, instances of URLClassLoader
and its subclasses and java.util.jar
automatically verify signatures of signed JAR files. Developer-implemented custom class loaders that subclass java.lang.ClassLoader
may lack this check. Moreover, even in the URLClassLoader
case, the automatic verification performs only an integrity check; it fails to authenticate the loaded class because the check only uses a the public key contained within the JAR and does not validate the public key. The legitimate JAR file may be replaced with a malicious JAR file containing a different public key along with appropriately modified digest values.
...
This noncompliant code example demonstrates the JarRunner
application, which can be used to dynamically execute a particular class residing within a JAR file (abridged version of the class in The Java Tutorials [Tutorials 2008]). It creates a JarClassLoader
that loads an application update, plug-in, or patch over an untrusted network such as the Internet. The URL to fetch the code is specified as the first argument (for example, http://www.securecoding.cert.org/software-updates.jar); any other arguments specify the arguments that are to be passed to the class that is loaded. JarRunner
uses reflection to invoke the main()
method of the loaded class. Unfortunately, by default, JarClassLoader
verifies the signature using the public key contained within the JAR file.
Code Block | ||
---|---|---|
| ||
public class JarRunner { public static void main(String[] args) throws IOException, ClassNotFoundException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException { URL url = new URL(args[0]); // Create the class loader for the application jar file JarClassLoader cl = new JarClassLoader(url); // Get the application's main class name String name = cl.getMainClassName(); // Get arguments for the application String[] newArgs = new String[args.length - 1]; System.arraycopy(args, 1, newArgs, 0, newArgs.length); // Invoke application's main class cl.invokeClass(name, newArgs); } } final class JarClassLoader extends URLClassLoader { private URL url; public JarClassLoader(URL url) { super(new URL[] { url }); this.url = url; } public String getMainClassName() throws IOException { URL u = new URL("jar", "", url + "!/"); JarURLConnection uc = (JarURLConnection) u.openConnection(); Attributes attr = uc.getMainAttributes(); return attr != null ? attr.getValue(Attributes.Name.MAIN_CLASS) : null; } public void invokeClass(String name, String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException { Class c = loadClass(name); Method m = c.getMethod("main", new Class[] { args.getClass() }); m.setAccessible(true); int mods = m.getModifiers(); if (m.getReturnType() != void.class || !Modifier.isStatic(mods) || || !Modifier.isPublic(mods)) { throw new NoSuchMethodException("main"); } try { m.invoke(null, new Object[] { args }); } catch (IllegalAccessException e) { System.out.println("Access denied"); } } } |
Compliant Solution (jarsigner
)
...
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) { // return, do not execute if unsigned 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()); // user is the alias Certificate pubCert = ks.getCertificate("user"); // usercheck iswith the aliastrusted public key, else throws exception certs[0].verify(pubCert.getPublicKey()); // check with the trusted public key, else throws exception } |
Because the invokeClass()
method now has two additional exceptions in its throws
clause, the catch
block in the main()
method must be altered accordingly.
...
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e3aeac3e3eb777bb-2f554442-4fe24503-a71e9bb9-46aa2648d8e676fa172edd12"><ac:plain-text-body><![CDATA[ | [ISO/IEC TR 24772:2010 | http://www.aitcnet.org/isai/] | " Improperly Verified Signature [XZR] " | ]]></ac:plain-text-body></ac:structured-macro> |
CWE-300, ". Channel Accessible accessible by Nonnon-Endpoint endpoint (aka 'Man"man-in-the-Middle'middle") " | ||||
| CWE-319, ". Cleartext Transmission of Sensitive Information" transmission of sensitive information | |||
| CWE-494, ". Download of Code Without Integrity Check" code without integrity check | |||
| CWE-347, ". Improper Verification of Cryptographic Signature" verification of cryptographic signature |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="201e51248a001c79-ed40fcc7-4dfb405f-9c1db29f-fcefcc75c052febf12f7fd68"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4f6e0e6674595070-c713c742-42094047-8bbfb734-70d8b97aa04406c2a555cd61"><ac:plain-text-body><![CDATA[ | [[Bea 2008 | AA. Bibliography#Bea 08]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e0bea7442995c95f-de34b743-469144be-b83f8dd5-74eaeddeab8c8eea8b828fc5"><ac:plain-text-body><![CDATA[ | [[Eclipse 2008 | AA. Bibliography#Eclipse 08]] | [JAR Signing | http://wiki.eclipse.org/JAR_Signing] and [Signed bundles and protecting against malicious code | http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/guide] | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6ba2e800ea5a5155-58ed1a39-4f8d4931-8b7d8f3f-886e49d1a6f0e9f523897303"><ac:plain-text-body><![CDATA[ | [[Fairbanks 2007 | AA. Bibliography#Fairbanks 07]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f19d82bf79501ee0-f535dba0-4dea4c52-a407bdfa-0db9db05719977a994efc40d"><ac:plain-text-body><![CDATA[ | [[Flanagan 2005 | AA. Bibliography#Flanagan 05]] | Chapter 24. , The | ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6394de5aa88d88ee-5f8d6061-48fe4e83-a7a6b6d0-f7e4fb5c67431daaec4b753f"><ac:plain-text-body><![CDATA[ | [[Gong 2003 | AA. Bibliography#Gong 03]] | 12.8.3, | ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4930d7aef172fff0-1efe4d9a-40d340fb-bc9b8cd7-36f2aa3c5bd3445367c8d7ce"><ac:plain-text-body><![CDATA[ | [[Halloway 2001 | AA. Bibliography#Halloway 01]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="e16e950c47f991c7-ad93d155-43f242d1-90318fbb-04f37b96a1378e52c971cada"><ac:plain-text-body><![CDATA[ | [[JarSpec 2008 | AA. Bibliography#JarSpec 08]] | Signature Validation |
| ]]></ac:plain-text-body></ac:structured-macro> | ||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="a278b337603ec420-0f7a884b-459947ea-a302b70a-0bf0dc8c9519a1bb4e661bf9"><ac:plain-text-body><![CDATA[ | [[Oaks 2001 | AA. Bibliography#Oaks 01]] | Chapter 12: , Digital Signatures, Signed Classes | ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="25df8d1331b2b0e6-3434ada7-483f4fe1-be5fb2c7-9c516c1f6efcc11454c497a6"><ac:plain-text-body><![CDATA[ | [[Muchow 2001 | AA. Bibliography#Muchow 01]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9059626ebf58dfc1-17d4bfb3-45ee45cd-bcfa9bdd-6e1f77cf0750e6a41afb1efb"><ac:plain-text-body><![CDATA[ | [[Tutorials 2008 | AA. Bibliography#Tutorials 08]] | [The | http://java.sun.com/docs/books/tutorial/deployment/jar/jarrunner.html], [Lesson: API and Tools Use for Secure Code and File Exchanges | http://java.sun.com/docs/books/tutorial/security/sigcert/index.html] and [Verifying Signed JAR Files | http://java.sun.com/docs/books/tutorial/deployment/jar/verify.html] | ]]></ac:plain-text-body></ac:structured-macro> |
...