...
This noncompliant code example includes a doPrivileged()
block and calls a method defined in a class in a different, untrusted JAR file.
Code Block | ||
---|---|---|
| ||
package trusted;
import untrusted.RetValue;
public class MixMatch {
private void privilegedMethod() throws IOException {
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException, FileNotFoundException {
final FileInputStream fis = new FileInputStream("file.txt");
try {
RetValue rt = new RetValue();
if (rt.getValue() == 1) {
// do something with sensitive file
}
} finally {
fis.close();
}
return null; // nothing to return.
}
}
);
} 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;
}
}
|
...
This noncompliant code example improves upon the previous example by moving the use 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;
}
}
|
...
This compliant solution combines all security-sensitive code into the same package and the 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;
}
}
|
To seal a package, use the sealed
attribute in the JAR file's manifest file header, as follows.
Code Block |
---|
Name: trusted/ // package name
Sealed: true // sealed attribute
|
...
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 is feasible.
Android Implementation Details
java.security.AccessController
exists on Android for compatibility purposes only and it should not be used.
Related Guidelines
...
[EMA 2011] | Optional Package Sealing |
Rule 7, If you must sign your code, put it all in one archive file | |
|