In Java SE 6, privileged code either uses the AccessController
mechanism or must be signed by an owner (or provider) who is trusted by the user. Attackers could link privileged code with malicious code if the privileged code directly or indirectly invokes code from another package. In fact, a trusted jar file often contains code that is not privileged, but depends on privileged code, this is known as security-sensitive code. If an attacker can link security-sensitive code with malicious code, they can indirectly cause incorrect behavior with sensitive data. This is called a mix and match attack. A mix and match attack is not possible if the code is signed because, by default, the jarsigner
tool signs the finished manifest that contains the names of the included classes along with their digests.
Execution of untrusted code causes loss of privileges. If trusted code calls some untrusted code that attempts to perform some action requiring permissions not granted by the security policy, the action is not allowed. However, privileged code may use a class that exists in an untrusted container, performing only unprivileged operations. If the attacker replaces this class with a malicious implementation, the trusted code will retrieve incorrect results.
...
Sealing a JAR
file automatically enforces the requirement of keeping privileged code together. In addition, it is important to adhere to rule OBJ15-J. Minimize the accessibility of classes and their members.
Noncompliant Code Example (privileged code)
This noncompliant code example uses a doPrivileged
block and calls a method defined in a class that exists in a different, untrusted packagejar file.
Code Block | ||
---|---|---|
| ||
package trusted; import untrusted.RetValue; public class MixMatch { private void privilegedMethod() throws IOException { try { final FileInputStream fis = AccessController.doPrivileged( new PrivilegedExceptionAction<FileInputStream>() { public FileInputStream run() throws FileNotFoundException { final returnFileInputStream fis = new FileInputStream("file.txt"); } }try { ); try { RetValue rt = new RetValue(); if (rt.getValue() == 1) { // do something with sensitive file } } finally { fis.close(); } } } ); } catch (PrivilegedActionException e) { // forward to handler and log } } public static void main(String[] args) throws IOException { MixMatch mm = new MixMatch(); mm.privilegedMethod(); } } // In another jar file: package untrusted; class RetValue { public int getValue() { return 1; } } |
An attacker can provide an implementation of class RetValue
so that the privileged code uses the wrong return value. Even if class MixMatch
consists only of trusted only , signed code, an attacker can still cause this behavior by maliciously deploying a legally signed class in the class path of the privileged codejar file containing the untrusted RetValue
class.
Noncompliant Code Example (security-sensitive code)
This noncompliant code example improves upon the previous one by moving usage of the RetValue
class outside the doPrivileged()
block.
Code Block | ||
---|---|---|
| ||
package trusted;
import untrusted.RetValue;
public class MixMatch {
private void privilegedMethod() throws IOException {
try {
final FileInputStream fis = AccessController.doPrivileged(
new PrivilegedExceptionAction<FileInputStream>() {
public FileInputStream run() throws FileNotFoundException {
return new FileInputStream("file.txt");
}
}
);
try {
RetValue rt = new RetValue();
if (rt.getValue() == 1) {
// do something with sensitive file
}
} finally {
fis.close();
}
} catch (PrivilegedActionException e) {
// forward to handler and log
}
}
public static void main(String[] args) throws IOException {
MixMatch mm = new MixMatch();
mm.privilegedMethod();
}
}
// In another jar file:
package untrusted;
class RetValue {
public int getValue() {
return 1;
}
}
|
While the RetValue
class is not used within the doPrivileged()
block, the behavior of RetValue.getValue()
certainly affects the behavior of security-sensitive code; that is, the code that operates on the file opened within the doPrivileged()
block. So an attacker can still exploit the security-sensitive code with a malicious implementation of RetValue
.
Compliant Solution
This compliant solution combines all privileged security-sensitive code into the same package and an dthe same jar file. It also reduces the accessibility of the getValue()
method to package-private. Sealing the package is necessary to prevent attackers from inserting any rogue classes.
Code Block | ||
---|---|---|
| ||
package trusted; public class MixMatch { // ... } // In the same signed & sealed jar file: package trusted; class RetValue { int getValue() { return 1; } } |
...
Code Block |
---|
Name: trusted/ // package name Sealed: true // sealed attribute |
Exception
ENV01-EX1EX0: Independent groups of privileged code may be placed in separate sealed packages. The enabling condition is that the code in any one of these packages lacks any dynamic or static dependency on any of the other packages. This means that code from one such package must not invoke code from any of the others, whether directly or transitively.
Risk Assessment
Failure to place all privileged code together in one package and seal the package can lead to mix and match attacks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ENV01-J | high | probable | medium | P12 | L1 |
Automated Detection
Detecting code that should be considered privileged or sensitive requires programmer assistance. Given identified privileged code as a starting point, automated tools could compute the closure of all code that can be invoked from that point. Such a tool could plausibly determine whether all code in that closure exists within a single package. A further check of whether the package is sealed appears feasible.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
MITRE CWE: CWE-349: Acceptance of Extraneous Untrusted Data With Trusted Data
Bibliography
Wiki Markup |
---|
\[[API 2006|AA. Bibliography#API 06]\] \[[McGraw 1999|AA. Bibliography#Ware 99]\] Rule 7: If You Must Sign Your Code, Put It All in One Archive File (sic) \[[Ware 2008|AA. Bibliography#Ware 08]\] |
...