Wiki Markup |
---|
Code is usually signed when it requires more than the default set of permissions to perform some tasks. Although it is |
often a bad idea to sign code (_c.f._ \[[ENV00-J. Do not sign code that performs only unprivileged operations]\]), some actions necessitate this step. For example, if |
http
connection with an external host to download plugins or extensions, a vendor may provide signed code instead of having the user deal with complex security policies. Because executing signed code can be extremely dangerous, verifying authenticity of origin is of utmost importance. an application requires an {{http}} connection with an external host to download plugins or extensions, its vendor may provide signed code rather than requiring that the user deal with complex security policies. Because executing 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 independent deployment. Be it desktop applications, JAR files are the preferred means of distribution for Enterprise Java Beans (EJB), MIDlets (J2ME) or and Weblogic Server J2EE applications, JAR files are the preferred means of distributionfor 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, however, this should not be interpreted to be the case that the code cannot be misused. This certifies the authenticity of the code; it cannot guarantee the safety of the code.
Wiki Markup |
---|
According to the Java Tutorials \[[Tutorials 2008|AA. Bibliography#Tutorials 08]\] |
If you are creating applet code that you will sign, it needs to be placed in a JAR file. The same is true if you are creating application code that may be similarly restricted by running it with a security manager. The reason you need the JAR file is that when a policy file specifies that code signed by a particular entity is permitted one or more operations, such as specific file reads or writes, the code is expected to come from a signed JAR file. (The term "signed code" is an abbreviated way of saying "code in a class file that appears in a JAR file that was signed.")
Depending on how the client code works, signatures may or may not be automatically checked programaticallyClient code may lack programatic checks of code signatures. For example, any instances of URLClassLoader
and its subclasses and java.util.jar
automatically verify a signature whenever the JAR file is signed. If however, the developer implements a custom classloader that goes on to signatures of signed JAR files. Developer-implemented custom classloaders that subclass java.lang.ClassLoader
, this step is not performed automatically may lack this check. Moreover, even in the URLClassLoader
case, the automatic verification just involves performs only an integrity check and does not ; it fails to authenticate the loaded class . This is because the check uses a public key that is contained within the JAR. The legitimate JAR file may be replaced with a malicious JAR file containing a different public key and along with appropriately modified digest values.
Noncompliant Code Example
This noncompliant code example demonstrates the JarRunner
application that which can be used to dynamically execute a particular class residing within a JAR file (abridged version of the class in [Tutorials 2008]). It creates a JarClassLoader
that loads an application update, plugin 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://somewebsite.com/software-updates.jar) and ; any other arguments specify the arguments that are to be passed to the class to be that is loaded. Reflection is used 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,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); } } 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
If the program expects the user to manually install the new JAR file, the user can explicitly check the signature from the command lineUsers can — but usually do not — explicitly check JAR file signatures at the command line; this may be an adequate solution for programs that require manual installation of JAR files. Any malicious tampering results in a SecurityException
when the jarsigner
tool is invoked with the -verify
option.
...
When the local system cannot reliably verify the signature, an explicit signature verification check must be built within the invoking program . This can be achieved must verify the signature programmatically by obtaining the chain of certificates from the CodeSource
of the class being loaded and checking if whether any one of the certificates belongs to the a trusted signer whose certificate has been securely obtained beforehand and stored in a local keystore. The invokeClass
method can be modified to do this as shown in this compliant solutionThis compliant solution demonstrates the necessary modifications to the invokeClass
method.
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 Because the invokeClass
method now has two more additional exceptions in its throws
clause, so the catch
block in the main
method must be altered accordingly.)
The It is not always the case that arbitrary code gets executed. By default, the URLClassLoader
and all its subclasses are given by default only given enough permissions to interact with the URL
that was specified when the URLClassLoader
object was created. This means that the program loaded code can interact only interact with the specified host. However, this does not This fails to mitigate the risk completely, however, as the loaded file code may have been granted appropriate privileges to perform that permit other sensitive operations such as updating an existing local JAR file.
Risk Assessment
Not verifying the Failure to verify a digital signature either , whether manually or programmatically, can lead to the execution of malicious code.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SEC19-J | high | probable | medium | P12 | L1 |
Automated Detection
Wiki Markup |
---|
Automated detection is not feasible in the fully general case. However, an approach similar to Design Fragments \[[Fairbanks 07|AA. Bibliography#Fairbanks 07]\] could assist both programmers and static analysis tools. |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
...
Wiki Markup |
---|
\[[API 2006|AA. Bibliography#API 06]\] \[[GongBea 20032008|AA. Bibliography#GongBibliography#Bea 0308]\] 12.8.3 jarsigner \[[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] \[[HallowayFairbanks 200107|AA. Bibliography#HallowayBibliography#Fairbanks 0107]\] \[[Flanagan 2005|AA. Bibliography#Flanagan 05]\] Chapter 24. The java.util.jar Package \[[OaksGong 20012003|AA. Bibliography#OaksBibliography#Gong 0103]\] Chapter 12: Digital Signatures, Signed Classes12.8.3 jarsigner \[[TutorialsHalloway 20082001|AA. Bibliography#TutorialsBibliography#Halloway 08]\] [The JarRunner Class|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]01]\] \[[JarSpec 2008|AA. Bibliography#JarSpec 08]\] Signature Validation \[[Bea 2008|AA. Bibliography#Bea 08]\] \[[Muchow 2001|AA. Bibliography#Muchow 01]\] \[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID 300|http://cwe.mitre.org/data/definitions/300.html] "Channel Accessible by Non-Endpoint (aka 'Man-in-the-Middle')", [CWE ID 319|http://cwe.mitre.org/data/definitions/319.html] "Cleartext Transmission of Sensitive Information", [CWE ID 494|http://cwe.mitre.org/data/definitions/494.html] "Download of Code Without Integrity Check", [CWE ID 347|http://cwe.mitre.org/data/definitions/347.html] "Improperly Verified Signature"\[[Oaks 2001|AA. Bibliography#Oaks 01]\] Chapter 12: Digital Signatures, Signed Classes \[[Muchow 2001|AA. Bibliography#Muchow 01]\] \[[Tutorials 2008|AA. Bibliography#Tutorials 08]\] [The JarRunner Class|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] |
...
SEC18-J. Define wrappers around native methods 02. Platform Security (SEC) 03. Declarations and Initialization (DCL)