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 vector. 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.
Noncompliant Code Example
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.
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; } }
Compliant Solution
TODO