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. should be signed only if it requires elevated privileges to perform one or more tasks (see ENV00-J. Do not sign code that performs only unprivileged operations), some actions necessitate this step for more information). For example, if an application requires an http
applets are denied the privilege of making HTTP connections to any hosts except the host from which they came. 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 requiring that force the user deal with complex security policiesto arbitrarily assign 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 Signing certifies the authenticity of the code; , but it cannot guarantee the safety security of the code.unmigrated-wiki-markup
According to the Java Tutorials \ [[Tutorials 2008|AA. Bibliography#Tutorials 08]\]Java Tutorials],
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.")
Client code may lack programatic programmatic checks of code signatures. For example, any instances of URLClassLoader
and its subclasses and java.util.jar
automatically verify signatures of signed JAR files. Developer-implemented custom classloaders that subclass java.lang.ClassLoader
class loaders 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 uses a the public key contained within the JAR without validating 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.
The default automatic signature verification process may still be used , but is not sufficient. Systems that use the default automatic signature verification process must perform additional checks to ensure that the signature is correct (such as comparing it against a known trusted signature).
Noncompliant Code Example
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 [Java Tutorials 2008]). It creates a JarClassLoader
that loads an application update, plugin 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://somewebsite.comwww.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
)
Users can — but can—but usually do not — explicitly not—explicitly check JAR file signatures at the command line; this . This solution 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.
Code Block | ||
---|---|---|
| ||
jarsigner -verify signed-updates-jar-file.jar
|
Compliant Solution (
...
Certificate Chain)
When the local system cannot reliably verify the signature, the invoking program must verify the signature programmatically by obtaining the chain of certificates from the CodeSource
of the class being loaded and checking whether any of the certificates belongs belong to a trusted signer whose certificate has been securely obtained beforehand and stored in a local keystore. This 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) { // 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 alias trusted 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.
The URLClassLoader
and all its subclasses are given by default only enough permissions to interact with the URL
that was specified when the URLClassLoader
object was created. This , which means that the loaded code can interact only with the specified host. This It fails to mitigate the risk completely, however, as because the loaded code may have been granted privileges that permit other sensitive operations such as updating an existing local JAR file.
Risk Assessment
Failure to verify a digital signature, whether manually or programmatically, can lead to result in the execution of malicious code.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
SEC06-J |
High |
Probable |
Medium | P12 | L1 |
Automated Detection
...
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 rule on the CERT website.
Related Guidelines
2007] could assist both programmers and static analysis tools.
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| JAVA.IO.INJ.ANDROID.MESSAGE | Android Message Injection (Java) |
Related Guidelines
Improperly Verified Signature [XZR] | |
CWE-300, Channel Accessible by Non-endpoint (aka " |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="dce5a016-26c2-487d-93aa-c831298f8c84"><ac:plain-text-body><![CDATA[
[[MITRE 2009
AA. Bibliography#MITRE 09]]
[CWE ID 300
Man-in-the-Middle |
") |
]]></ac:plain-text-body></ac:structured-macro>
Cleartext Transmission of Sensitive Information |
|
, Download of Code |
without Integrity Check |
Bibliography
[ |
[[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="7c3f1b9e-d8dc-4e7d-a141-63384eaab180"><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="9b88f229-6173-49b7-a959-b42858cfd31c"><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="be65b4ac-10f2-4af0-873d-af23f10b9120"><ac:plain-text-body><![CDATA[
[[Fairbanks 07
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="cb28f757-5fad-4a36-bef7-482b324eaf3f"><ac:plain-text-body><![CDATA[
[[Flanagan 2005
AA. Bibliography#Flanagan 05]]
Chapter 24. The java.util.jar Package
]]></ac:plain-text-body></ac:structured-macro>
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4ce29dba-ffc2-417f-9109-2440ac2fac0d"><ac:plain-text-body><![CDATA[
[[Gong 2003
AA. Bibliography#Gong 03]]
12.8.3 jarsigner
]]></ac:plain-text-body></ac:structured-macro>
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c3af519a-efba-40cb-a2d9-c6ce93d41e8c"><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="a5c20a93-c426-4d9b-9ae5-737db317bfe4"><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="e8d93ef1-f9ac-438a-b736-3c0c1b1b0ad7"><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="ffacc675-7891-4498-97de-bfb564f1b71e"><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="a9f1ae22-44d2-454d-b4db-4680821c5478"><ac:plain-text-body><![CDATA[
[[Tutorials 2008
AA. Bibliography#Tutorials 08]]
[The JarRunner Class
[Bea 2008] | |
JAR Signing | |
Chapter 24, "The | |
Section 12.8.3, " | |
Signature Validation | |
Lesson: API and Tools Use for Secure Code and File Exchanges |
http://java.sun.com/docs/books/tutorial/deployment/jar/verify.html]
]]></ac:plain-text-body></ac:structured-macro>
[Muchow 2001] | |
Chapter 12, "Digital Signatures, Signed Classes" |
...
SEC18-J. Define wrappers around native methods 14. Platform Security (SEC) SEC21-J. Remove superfluous code from privileged blocks