Enforcing Java Security Manager in Restricted Windows Environments

Good morning

Currently I am working on a Terminal-Server-Project which provides applications to users. Through Software Restriction Policys the users are restricted to a certain set of executables (Whitelisting). One of these permitted executables is java.exe. So if Java is enabled any Java Application can be executed on the system. This allows a malicious user to execute arbitrary Java code, like replacement shells (JSH), RDP clients (Propero Java RDP), network port scanners etc. I could block java.exe but the business requirement are that the company's Java application must still work. This lead me into this research on how to whitelist Java applications in a restricted Windows environment.

First of all Java has a mechanism called Java2 Security which allows to implement policies based on code location on disk or digital signatures. These policies are configured through the files java.policy and java.security. When java.exe gets executed these policies are not enforced. To enforce the Java system property java.security.manager must included on startup: java.exe -Djava.security.manager MyCode

This poperty causes Java's Security Manager to be installed and the policy to be enforced. So fare so good. But how can I pass this parameter without having it to be specified on the command line?

Well Java offers the environment variable _JAVA_OPTIONS. So I thought I place the parameter into a Windows System Environment Variable: _JAVA_OPTIONS=-Djava.security.manager=

Testing showed that java.exe can be executed with Security Manager without passing the parameter on the command line directly. Further testing revealed that when I start a cmd.exe as a low-privileged user I can overwrite this System Environment Variable and I can bypass the Java Security Manager: set _JAVA_OPTIONS=

I try the same from within a Microsoft Word. Effect is the same. According to my research and feedback from Microsoft the System Environment Variables can be overwritten within the process for the local process. For details see: http://www.virusbtn.com/files/johnlambert_vb2002.pdf. On page 13 in Chapter "Analysis of Path Rule" there it is written: "Environment variables are not secure, and any user who can load a command prompt can temporarily redefine them."

So this melts down to my question: Is there a way to tell java.exe to always use the Java Security Manager without the possiblity of manipulation by the user?

Kind regards

Jan P. Monsch

Malware.java:

import java.io.*;

public class Malware {

public static void main(String[] inArguments) {

try {

FileOutputStream fos = new FileOutputStream("touch.txt");

fos.close();

}

catch (IOException e) {

e.printStackTrace();

}

finally {

System.out.flush();

try {

Thread.sleep(5000);

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

java.policy:

grant {

//Empty -> no privileges

};

java.security:

security.provider.1=sun.security.provider.Sun

security.provider.2=com.sun.net.ssl.internal.ssl.Provider

security.provider.3=com.sun.rsajca.Provider

security.provider.4=com.sun.crypto.provider.SunJCE

security.provider.5=sun.security.jgss.SunProvider

securerandom.source=file:/dev/random

login.configuration.provider=com.sun.security.auth.login.ConfigFile

policy.provider=sun.security.provider.PolicyFile

policy.url.1=file:${java.home}/lib/security/java.policy

policy.expandProperties=true

policy.allowSystemProperty=false

policy.ignoreIdentityScope=false

keystore.type=jks

system.scope=sun.security.provider.IdentityDatabase

package.access=sun.

security.overridePropertiesFile=false

ssl.KeyManagerFactory.algorithm=SunX509

ssl.TrustManagerFactory.algorithm=SunX509

networkaddress.cache.negative.ttl=10

Word Makro:

Private Declare Function SetEnvironmentVariable Lib "kernel32.dll" Alias

"SetEnvironmentVariableA" (ByVal lpName As String, ByVal lpValue As

String) As Long

Sub StartCmdExe()

SetEnvironmentVariable "_JAVA_OPTIONS", "-Dasdf"

StartProgram "C:\PROGRA~1\JAVA\J2RE14~1.2_1\BIN\java.exe Malware"

End Sub

Sub StartProgram(Path)

Dim shellObj As WshShell

Set shellObj = New WshShell

shellObj.CurrentDirectory = "C:\PROGRA~1\JAVA\J2RE14~1.2_1\BIN\"

shellObj.Run Path

End Sub

[4568 byte] By [jan_monscha] at [2007-10-3 6:05:29]
# 1

You should not deploy java.exe in a shared environments where multiple trusted users use the same JVM. There are simply to many JVM level vulnerabilities where one user will be able to use the very recent series of JVM level bugs that can inspect the running code of another user, not to mention the problems you mentioned where a user can run Java shells, network sniffers, and other nasties.

You only want to do this in the J2EE world where you are protected behind many layers of protections between the user and the JVM.

But what you are suggesting is an environment where many users can directly share the same JVM, and even with your security policy restrictions, like you said, I can do some simple OS parameter tampering to get around that.

Answer: do not do it. Shared JVM's only belong in the Servlet/J2EE work - and even then, JVM level exploits still get exposed from container endpoints, like we see in JBOSS often.

Jim_Manicoa at 2007-7-15 0:48:11 > top of Java-index,Security,Other Security APIs, Tools, and Issues...