Typically, privileged code uses the AccessController mechanism or needs to be signed by the provider. An adversary is capable of linking privileged code with malicious code. This is called mix and match attack. A mix and match attack is not possible if the code is signed because by default, jarsigner signs the finished manifest that contains the names of the included classes along with their digests.
Privileges are lost as soon as untrusted code is executed. However, privileged code may attempt to use a class that exists in an untrusted container. If the attacker replaces this class with a malicious implementation, the application can be exploited.
According to the Java API \[[JarSpec 08|AA. Java References#JarSpec 08]\], {{JAR}} file specification: |
A package sealed within a
JARspecifies that all classes defined in that package must originate from the sameJAR. Otherwise, aSecurityExceptionis thrown.
Sealing a JAR file automatically enforces the requirement of keeping privileged code together. In addition, it is important to adhere to SEC05-J. Minimize accessibility of classes and their members.
This noncompliant code example uses a doPrivileged block and calls a method defined in a class that exists in a different package which is untrusted. An attacker can provide an implementation of class RetValue so that the privileged code uses the wrong value. If class MixMatch trusted only signed code, even then an attacker can cause this behavior by maliciously using a legibly signed class and linking it to the privileged code.
package trusted;
import untrusted.RetValue;
public class MixMatch {
private void privilegedMethod() throws IOException {
try {
FileInputStream fis
= (FileInputStream) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public FileInputStream run() throws FileNotFoundException {
return new FileInputStream("file.txt");
}
}
);
RetValue rt = new RetValue();
if(rt.getValue() == 1) {
// do something sensitive file
}
} catch (PrivilegedActionException e) { /* forward to handler and log */ }
}
public static void main(String[] args) throws IOException {
MixMatch mm = new MixMatch();
mm.privilegedMethod();
}
}
package untrusted;
class RetValue {
public int getValue() {
return 1;
}
}
|
This compliant solution combines all privileged code into the same package. To prevent attackers from inserting any rogue classes, sealing the package is necessary.
package trusted;
public class MixMatch {
// ...
}
package untrusted;
package trusted;
class RetValue {
// ...
}
|
To seal a package, use the sealed attribute in the manifest file header. This is shown below.
Name: trusted/ // package name Sealed: true // sealed attribute |
Failure to place all privileged code together, in one package and then sealing the package can lead to mix and match attacks.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
ENV04- J |
high |
probable |
medium |
P12 |
L1 |
TODO
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
\[[API 06|AA. Java References#API 06]\] \[[Ware 08|AA. Java References#Ware 08]\] \[[McGraw 00|AA. Java References#Ware 00]\] Rule 7: If You Must Sign Your Code, Put It All in One Archive File (sic) \[[MITRE 09|AA. Java References#MITRE 09]\] [CWE-349: Acceptance of Extraneous Untrusted Data With Trusted Data|http://cwe.mitre.org/data/definitions/349.html] |
ENV03-J. Limit remote uses of JVM Monitoring and Managing 01. Runtime Environment (ENV) ENV30-J. Create a secure sandbox using a Security Manager