...
Java is a relatively secure language: there is no explicit pointer manipulation; array and string
bounds are automatically checked; attempts at referencing a null pointer are trapped; the
arithmetic operations are well defined and platform independent, as are the type conversions.
The built-in bytecode verifier ensures that these checks are always in place.
Moreover, there are comprehensive, fine-grained security mechanisms available in Java that
can control access to individual files, sockets, and other sensitive resources. To take
advantage of the security mechanisms, the Java Virtual Machine (JVM) must have a
security manager in place. This is an ordinary Java object of class java.lang.SecurityManager
(or a subclass) that can be put in place programmatically but is more usually specified via a command line parameter.
...
If these two types could be confused, it would be possible to access the private field
theCrownJewels
as if it were the public field myCostumeJewerly
. More generally, a âtype
type confusion attackâ attack could allow Java security to be compromised by making the internals of the
security manager open to abuse. A team of researchers at Princeton University showed that
any type confusion in Java could be used to completely overcome Javaâs security
mechanisms (see Securing Java Ch. 5, Sec. 7 McGraw 99).
Javaâs type safety means that fields that are declared private or protected or that have
default (package) protection should not be globally accessible. However, there are a number
of vulnerabilities âbuilt inâ to Java that enable this protection to be overcome. These should
come as no surprise to the Java expert, as they are well documented, but they may trap the
unwary.
Public Fields
A field that is declared public may be directly accessed by any part of a Java program and
may be modified from anywhere in a Java program (unless the field is declared final).
Clearly, sensitive information must not be stored in a public field, as it could be
compromised by anyone who could access the JVM running the program.
...
Inner classes have access to all the fields of their surrounding class. There is no bytecode
support for inner classes, so they are compiled into ordinary classes with names like
OuterClass$InnerClass. So that the inner class can access the private fields of the
outer class, the private access is changed to package access in the bytecode. For that reason, handcrafted bytecode can access these private fields (see âSecurity Aspects in Java Bytecode
Engineeringâ Schönefeld 02 for an example).
...
Serialization enables the state of a Java program to be captured and written out to a byte
stream Sun 04b. This allows for the state to be preserved so that it can be reinstated (by
deserialization). Serialization also allows for Java method calls to be transmitted over a
network for Remote Method Invocation (RMI). An object (called someObject below) can
be serialized as follows:
...
Serialization captures all the fields of a class, provided the class implements the
Serializable
interface, including the non-public fields that are not normally accessible
(unless the field is declared transient). If the byte stream to which the serialized values
are written is readable, then the values of the normally inaccessible fields may be read.
Moreover, it may be possible to modify or forge the preserved values so that when the class
is deserialized, the values become corrupted.
Introducing a security manager does not prevent the normally inaccessible fields from being
serialized and deserialized (although permission must be granted to write to and read from
the file or network if the byte stream is being stored or transmitted). Network traffic
(including RMI) can be protected, however, by using SSL.
...
Reflection enables a Java program to analyze and modify itself. In particular, a program can
find out the values of field variables and change them Forman 05, Sun 02. The Java
reflection API includes a method call that enables fields that are not normally accessible to be
accessed under reflection. The following code prints out the names and values of all fields of
an object someObject
of class SomeClass:
Code Block |
---|
Field [ ] fields = SomeClass.getDeclaredFields( ); for (Field fieldsI : fields) { if ( !Modifier.isPublic (fieldsI.getModifiers( )) ) { fieldsI.setAccessible (true); } System.out.print (âField: â + fieldsI.getName( )); System.out.println (â, value: â + fieldsI.get (someObject)); } |
...
Introducing the default security manager does prevent the fields that would not normally be
accessible from being accessed under reflection. The default security manager throws
java.security.AccessControlException
in these circumstances. However, it is
possible to grant a permission to override this default behavior:
java.lang.reflect.ReflectPermission
can be granted with action suppressAccessChecks
.
...
Java 5 introduced the JVM Tool Interface (JVMTI) Sun 04d, replacing both the JVM
Profiler Interface (JVMPI) and the JVM Debug Interface (JVMDI), which are now
deprecated.
The JVMTI contains extensive facilities to find out about the internals of a running JVM,
including facilities to monitor and modify a running Java program. These facilities are rather
low level and require the use of the Java Native Interface (JNI) and C Language
programming. However, they provide the opportunity to access fields that would not
normally be accessible. Also, there are facilities that can change the behavior of a running
Java program (for example, threads can be suspended or stopped).
The JVMTI works by using agents that communicate with the running JVM. These agents
must be loaded at JVM startup and are usually specified via one of the command line options
{{â“agentlib:}} or {{â“agentpath:}}. However, agents can be specified in environment
variables, although this feature can be disabled where security is a concern. The JVMTI is
always enabled, and JVMTI agents may run under the default security manager without
requiring any permissions to be granted. More work needs to be done to determine under
exactly what circumstances the JVMTI can be misused.
...
The Java Platform Debugger Architecture (JPDA) builds on the JVMTI and provides highlevel
facilities for debugging running Java systems Sun 04c. These include facilities similar
to the reflection facilities described above for inspecting and modifying field values. In
particular, there are methods to get and set field and array values. Access control is not
enforced so, for example, even the values of private fields can be set.
Introducing the default security manager means that various permissions must be granted in
order for debugging to take place. The following policy file was used to run the JPDS Trace
demonstration under the default security manager:
...
Java contains extensive facilities for monitoring and managing a JVM Sun 04e. In
particular, the Java Management Extension (JMX) API enables the monitoring and control of
class loading, thread state and stack traces, deadlock detection, memory usage, garbage
collection, operating system information, and other operations Sun 04a. There are also
facilities for logging monitoring and management. A running JVM may be monitored and
managed remotely.
For a JVM to be monitored and managed remotely, it must be started with various system
properties set (either on the command line or in a configuration file). Also, there are
provisions for the monitoring and management to be done securely (by passing the
information using SSL, for example) and to require proper authentication of the remote
server. However, users may start a JVM with remote monitoring and management enabled
with no security for their own purposes, and this would leave the JVM open to compromise
from outsiders. Although a user could not easily turn on remote monitoring and management
by accident, they might not realize that starting a JVM so enabled, without any security also
switched on, could leave their JVM exposed to outside abuse.