Secure Coding Guidelines For Java
Secure Coding Guidelines For Java
V 4.0, From oracle.com
Introduction
Fundamentals
1. Denial of Service
2. Confidential Information
3. Injection and Inclusion
4. Accessibility and Extensibility
5. Input Validation
6. Mutability
7. Object Construction
8. Serialization and Deserialization
9. Access Control
10. Conclusion
11. References
Introduction
One of the main design considerations for the Java platform is to provide a secure
environment for executing mobile code. Java comes with its own unique set of security
challenges. While the Java security architecture [1] can protect users and systems from
hostile programs downloaded over a network, it cannot defend against implementation
bugs that occur in trusted code. Such bugs can inadvertently open the very holes that the
security architecture was designed to contain, including access to files, printers, webcams,
microphones, and the network from behind firewalls. In severe cases local programs may
be executed or Java security disabled. These bugs can potentially be used to turn the
machine into a zombie computer, steal confidential data from machine and intranet, spy
through attached devices, prevent useful operation of the machine, assist further attacks,
and many other malicious activities.
The choice of language system impacts the robustness of any software program. The Java
language [2] and virtual machine [3] provide many features to mitigate common
programming mistakes. The language is typesafe, and the runtime provides automatic
memory management and boundschecking on arrays. Java programs and libraries check
for illegal state at the earliest opportunity. These features also make Java programs immune
to the stacksmashing [4] and buffer overflow attacks possible in the C and to a lesser
extent C++ programming languages. These attacks have been described as the single most
pernicious problem in computer security today [5]. The explicit static typing of Java makes
code easy to understand and the dynamic checks ensure unexpected conditions result in
predictable behaviour which makes Java a joy to use.
To minimize the likelihood of security vulnerabilities caused by programmer error, Java
developers should adhere to recommended coding guidelines. Existing publications, such
as Effective Java [6], provide excellent guidelines related to Java software design. Others,
such as Software Security: Building Security In [7], outline guiding principles for software
security. This paper bridges such publications together and includes coverage of additional
topics. This document provides a more complete set of securityspecific coding guidelines
targeted at the Java programming language. These guidelines are of interest to all Java
developers, whether they create trusted enduser applications and applets, implement the
internals of a security component, or develop shared Java class libraries that perform
common programming tasks. Any implementation bug can have serious security
ramifications and could appear in any layer of the software stack.
0 Fundamentals
The following general principles apply throughout Java security.
Guideline 00: Prefer to have obviously no flaws rather than no obvious flaws [8]
Creating secure code is not necessarily easy. Despite the unusually robust nature of Java,
flaws can slip past with surprising ease. Design and write code that does not require clever
logic to see that it is safe. Specifically, follow the guidelines in this document unless there is
a very strong reason not to.
Guideline 01: Design APIs to avoid security concerns
It is better to design APIs with security in mind. Trying to retrofit security into an existing
API is more difficult and error prone. For example, making a class final prevents a
malicious subclass from adding finalizers, cloning, and overriding random methods
(Guideline 45). Any use of the SecurityManager highlights an area that should be
scrutinized.
Guideline 02: Avoid duplication
Duplication of code and data causes many problems. Both code and data tend not to be
treated consistently when duplicated, e.g., changes may not be applied to all copies.
Guideline 03: Restrict privileges
Despite best efforts, not all coding flaws will be eliminated even in well reviewed code.
However, if the code is operating with reduced privileges, then exploitation of any flaws is
likely to be thwarted. The most extreme form of this is known as the principle of least
privilege. Using the Java security mechanism this can be implemented statically by
restricting permissions through policy files and dynamically with the use of the
java.security.AccessController.doPrivileged mechanism (see section 6). For
applets and JNLP applications the best approach is often to leave the jar files unsigned. The
application then runs in a sandbox and will not be able to execute any potentially
dangerous code. The application will be safe for the user to run because if it attempts to
execute securitysensitive code, the JRE will throw a security exception.
Guideline 04: Establish trust boundaries
In order to ensure that a system is protected, it is necessary to establish trust boundaries.
Data that crosses these boundaries should be sanitized and validated before use. Trust
boundaries are also necessary to allow security auditing to be performed efficiently. Code
that ensures integrity of trust boundaries must itself be loaded in such a way that its own
integrity is assured.
For instance, a web browser is outside of the system for a web server. Equally, a web
server is outside of the system for a web browser. Therefore, web browser and server
software should not rely upon the behavior of the other for security.
When auditing trust boundaries, there are some questions that should be kept in mind. Are
the code and data used sufficiently trusted? Could a library be replaced with a malicious
implementation? Is untrusted configuration data being used? Is code calling with lower
privileges adequately protected against?
Guideline 05: Minimise the number of permission checks
Guideline 06: Encapsulate
Allocate behaviors and provide succinct interfaces. Fields of objects should be private and
accessors avoided. The interface of a method, class, package, and module should form a
coherent set of behaviors, and no more.
1. 1 Denial of Service
Input into a system should be checked so that it will not cause excessive resource
consumption disproportionate to that used to request the service. Common affected
resources are CPU cycles, memory, disk space, and file descriptors.
In rare cases it may not be practical to ensure that the input is reasonable. It may be
necessary to carefully combine the resource checking with the logic of processing the data.
For client systems it is generally left to the user to close the application if it is using
excessive resources. Therefore, only attacks resulting in persistent DoS, such as wasting
significant disk space, need be defended against. Server systems should be robust against
external attacks.
Guideline 11: Beware of activities that may use disproportionate resources
Examples of attacks include:
Requesting a large image size for vector graphics. For instance, SVG and font files.
Integer overflow errors can cause sanity checking of sizes to fail.
An object graph constructed by parsing a text or binary stream may have memory
requirements many times that of the original data.
"Zip bombs" whereby a short file is very highly compressed. For instance, ZIPs,
GIFs and gzip encoded http contents. When decompressing files it is better to set
limits on the decompressed data size rather than relying upon compressed size or
metadata.
"Billion laughs attack" whereby XML entity expansion causes an XML document to
grow dramatically during parsing. Set the
XMLConstants.FEATURE_SECURE_PROCESSING feature to enforce reasonable limits.
Causing many keys to be inserted into a hash table with the same hash code, turning
an algorithm of around O(n) into O(n2).
Regular expressions may exhibit catastrophic backtracking.
XPath expressions may consume arbitrary amounts of processor time.
Java deserialization and Java Beans XML deserialization of malicious data may
result in unbounded memory or CPU usage.
Detailed logging of unusual behavior may result in excessive output to log files.
Infinite loops can be caused by parsing some corner case data. Ensure that each
iteration of a loop makes some progress.
Guideline 12: Release resources in all cases
Exceptions are often overlooked. Resources should always be released promptly even if an
exception is thrown. Java SE 7 has a syntax enhancement (trywithresources) for
automatically handling the release of many resources.
For Java SE 6 code and resources without support for the enhanced feature, use the
standard resource acquisition and release. Attempts to rearrange this idiom typically result
in errors and makes the code significantly harder to follow.
Ensure that any output buffers are flushed in the case that output was otherwise successful.
If the flush fails, the code should exit via an exception.
Guideline 13: Resource limit checks should not suffer from integer overflow
The Java language provides bounds checking on arrays which mitigates the vast majority
of integer overflow attacks. However, all the primitive integer types silently overflow.
Therefore, take care when checking resource limits. This is particularly important on
persistent resources, such as disk space, where a reboot may not clear the problem.
Some checking can be rearranged so as to avoid overflow. With large values, current +
max could overflow to a negative value, which would always be less than max.
If performance is not a particular issue, a verbose approach is to use arbitrary sized integers.
A peculiarity of two's complement integer arithmetic is that the minimum negative value
does not have a matching positive value of the same magnitude. So, Integer.MIN_VALUE
== -Integer.MIN_VALUE, Integer.MIN_VALUE == Math.abs(Integer.MIN_VALUE)
and, for integer a, a < 0 does not imply -a > 0. The same edge case occurs for
Long.MIN_VALUE.
2. 2 Confidential Information
Confidential data should be readable only within a limited context. Data that is to be trusted
should not be exposed to tampering. Privileged code should not be executable through
intended interfaces.
Guideline 21: Purge sensitive information from exceptions
Exception objects may convey sensitive information. For example, if a method calls the
java.io.FileInputStream constructor to read an underlying configuration file and that
file is not present, a java.io.FileNotFoundException containing the file path is thrown.
Propagating this exception back to the method caller exposes the layout of the file system.
Many forms of attack require knowing or guessing locations of files.
Exposing a file path containing the current user's name or home directory exacerbates the
problem. SecurityManager checks guard this information when it is included in standard
system properties (such as user.home) and revealing it in exception messages effectively
allows these checks to be bypassed.
Internal exceptions should be caught and sanitized before propagating them to upstream
callers. The type of an exception may reveal sensitive information, even if the message has
been removed. For instance, FileNotFoundException reveals whether or not a given file
exists.
It is not necessary to sanitize exceptions containing information derived from caller inputs.
If a caller provides the name of a file to be opened, there is no need to sanitize any resulting
FileNotFoundException thrown. In this case the exception provides useful debugging
information.
Be careful when depending on an exception for security because its contents may change
in the future. Suppose a previous version of a library did not include a potentially sensitive
piece of information in the exception, and an existing client relied upon that for security.
For example, a library may throw an exception without a message. An application
programmer may look at this behavior and decide that it is okay to propagate the exception.
However, a later version of the library may add extra debugging information to the
exception message. The application exposes this additional information, even though the
application code itself may not have changed. Only include known, acceptable information
from an exception rather than filtering out some elements of the exception.
Exceptions may also include sensitive information about the configuration and internals of
the system. Do not pass exception information to end users unless one knows exactly what
it contains. For example, do not include exception stack traces inside HTML comments.
Guideline 22: Do not log highly sensitive information
Some information, such as Social Security numbers (SSNs) and passwords, is highly
sensitive. This information should not be kept for longer than necessary nor where it may
be seen, even by administrators. For instance, it should not be sent to log files and its
presence should not be detectable through searches. Some transient data may be kept in
mutable data structures, such as char arrays, and cleared immediately after use. Clearing
data structures has reduced effectiveness on typical Java runtime systems as objects are
moved in memory transparently to the programmer.
This guideline also has implications for implementation and use of lowerlevel libraries that
do not have semantic knowledge of the data they are dealing with. As an example, a low
level string parsing library may log the text it works on. An application may parse an SSN
with the library. This creates a situation where the SSNs are available to administrators with
access to the log files.
Guideline 23: Consider purging highly sensitive from memory after use
To narrow the window when highly sensitive information may appear in core dumps,
debugging, and confidentiality attacks, it may be appropriate to zero memory containing the
data immediately after use rather than waiting for the garbage collection mechanism
However, doing so does have negative consequences. Code quality will be compromised
with extra complications and mutable data structures. Libraries may make copies, leaving
the data in memory anyway. The operation of the virtual machine and operating system
may leave copies of the data in memory or even on disk.
3. 3 Injection and Inclusion
A very common form of attack involves causing a particular program to interpret data
crafted in such a way as to cause an unanticipated change of control. Typically, but not
always, this involves text formats.
Guideline 31: Generate valid formatting
Attacks using maliciously crafted inputs to cause incorrect formatting of outputs are well
documented [7]. Such attacks generally involve exploiting special characters in an input
string, incorrect escaping, or partial removal of special characters.
If the input string has a particular format, combining correction and validation is highly
errorprone. Parsing and canonicalization should be done before validation. If possible,
reject invalid data and any subsequent data, without attempting correction. For instance,
many network protocols are vulnerable to crosssite POST attacks, by interpreting the
HTTP body even though the HTTP header causes errors.
Use welltested libraries instead of ad hoc code. There are many libraries for creating
XML. Creating XML documents using raw text is errorprone. For unusual formats where
appropriate libraries do not exist, such as configuration files, create classes that cleanly
handle all formatting and only formatting code.
Guideline 32: Avoid dynamic SQL
It is well known that dynamically created SQL statements including untrusted input are
subject to command injection. This often takes the form of supplying an input containing a
quote character ( ') followed by SQL. Avoid dynamic SQL.
For parameterised SQL statements using Java Database Connectivity (JDBC), use
java.sql.PreparedStatement or java.sql.CallableStatement instead of
java.sql.Statement. In general, it is better to use a wellwritten, higherlevel library to
insulate application code from SQL. When using such a library, it is not necessary to limit
characters such as quote ( '). If text destined for XML/HTML is handled correctly during
output (Guideline 33), then it is unnecessary to disallow characters such as less than ( <) in
inputs to SQL.
Guideline 33: XML and HTML generation requires care
Cross Site Scripting (XSS) is a common vulnerability in web applications. This is generally
caused by inputs included in outputs without first validating the input. For example,
checking for illegal characters and escaping data properly. It is better to use a library that
constructs XML or HTML rather than attempting to insert escape codes in every field in
every document. In particular, be careful when using Java Server Pages (JSP).
Guideline 34: Avoid any untrusted data on the command line
When creating new processes, do not place any untrusted data on the command line.
Behavior is platformspecific, poorly documented, and frequently surprising. Malicious
data may, for instance, cause a single argument to be interpreted as an option (typically a
leading - on Unix or / on Windows) or as two separate arguments. Any data that needs to
be passed to the new process should be passed either as encoded arguments (e.g., Base64),
in a temporary file, or through a inherited channel.
Guideline 35: Restrict XML inclusion
XML Document Type Definitions (DTDs) allow URLs to be defined as system entities,
such as local files and http URLs within the local intranet or localhost. XML External
Entity (XXE) attacks insert local files into XML data which may then be accessible to the
client. Similar attacks may be made using XInclude, the XSLT document function, and the
XSLT import and include elements. The safe way to avoid these problems whilst
maintaining the power of XML is to reduce privileges as described in Guideline 92. You
may decide to give some access through this technique, such as inclusion to pages from the
sameorigin web site. Another approach, if such an API is available, is to set all entity
resolvers to safe implementations.
Note that this issue generally applies to the use of APIs that use XML but are not
specifically XML APIs.
Guideline 36: Care with BMP files
BMP images files may contain references to local ICC files. Whilst the contents of ICC
files is unlikely to be interesting, the act of attempting to read files may be an issue. Either
avoid BMP files, or reduce privileges as Guideline 92.
Guideline 37: Disable HTML display in Swing components
Many Swing pluggable lookandfeels interpret text in certain components starting with
<html> as HTML. If the text is from an untrusted source, an adversary may craft the
HTML such that other components appear to be present or to perform inclusion attacks.
To disable the HTML render feature, set the "html.disable" client property of each
component to Boolean.TRUE (no other Boolean true instance will do).
label.putClientProperty("html.disable", true);
Guideline 38: Take care interpreting untrusted code
Code can be hidden in a number of places. If the source is untrusted then a secure sandbox
must be constructed to run it in. Some examples of components or APIs that can potentially
execute untrusted code include:
Scripts run through the scripting API or similar.
By default the Sun implementation of the XSLT interpreter enables extensions to call
Java code. Set the javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING
feature to disable it.
Long Term Persistence of JavaBeans Components supports execution of Java
statements.
RMI and LDAP (RFC 2713) may allow loading of remote code specified by remote
connection. On the Oracle JDK, RMI remote code loading may be disabled by
setting the "java.rmi.server.codebase" system property. LDAP code loading is
disabled unless the "com.sun.jndi.ldap.object.trustURLCodebase" is set to
"true".
Many SQL implementations allow execution of code with effects outside of the
database itself.
4. 4 Accessibility and Extensibility
The task of securing a system is made easier by reducing the "attack surface" of the code.
Guideline 41: Limit the accessibility of classes, interfaces, methods, and fields
A Java package comprises a grouping of related Java classes and interfaces. Declare any
class or interface public if it is specified as part of a published API, otherwise, declare it
packageprivate. Similarly, declare class members and constructors (nested classes,
methods, or fields) public or protected as appropriate, if they are also part of the API.
Otherwise, declare them private or packageprivate to avoid exposing the implementation.
Note that members of interfaces are implicitly public.
Classes loaded by different loaders do not have packageprivate access to one another even
if they have the same package name. Classes in the same package loaded by the same class
loader must either share the same code signing certificate or not have a certificate at all. In
the Java virtual machine class loaders are responsible for defining packages. It is
recommended that, as a matter of course, packages are marked as sealed in the jar file
manifest.
Guideline 42: Limit the accessibility of packages
Containers may hide implementation code by adding to the package.access security
property. This property prevents untrusted classes from other class loaders linking and
using reflection on the specified package hierarchy. Care must be taken to ensure that
packages cannot be accessed by untrusted contexts before this property has been set.
This example code demonstrates how to append to the package.access security property.
Note that it is not threadsafe. This code should generally only appear once in a system.
Guideline 43: Isolate unrelated code
Containers should isolate unrelated application code and prevent packageprivate access
between code with different permissions. Even otherwise untrusted code is typically given
permissions to access its origin, and therefore untrusted code from different origins should
be isolated. The Java Plugin, for example, loads unrelated applets into separate class loader
instances and runs them in separate thread groups.
Some apparently global objects are actually local to applet or application contexts. Applets
loaded from different web sites will have different values returned from, for example,
java.awt.Frame.getFrames. Such static methods (and methods on true globals) use
information from the current thread and the class loaders of code on the stack to determine
which is the current context. This prevents malicious applets from interfering with applets
from other sites.
Mutable statics (see Guideline 611) and exceptions are common ways that isolation is
inadvertently breached.
Guideline 44: Limit exposure of ClassLoader instances
Access to ClassLoader instances allows certain operations that may be undesirable:
Access to classes that client code would not normally be able to access.
Retrieve information in the URLs of resources (actually opening the URL is limited
with the usual restrictions).
Assertion status may be turned on and off.
The instance may be casted to a subclass. ClassLoader subclasses frequently have
undesirable methods.
Guideline 45: Limit the extensibility of classes and methods
Design classes and methods for inheritance or declare them final [6]. Left nonfinal, a class
or method can be maliciously overridden by an attacker. A class that does not permit
subclassing is easier to implement and verify that it is secure. Prefer composition to
inheritance.
// Hide constructor.
private SensitiveClass(Behavior behavior) {
this.behavior = behavior;
}
// Guarded construction.
public static SensitiveClass newSensitiveClass(
Behavior behavior
){
// ... validate any arguments ...
Malicious subclasses that override the Object.finalize method can resurrect objects
even if an exception was thrown from the constructor. Lowlevel classes with constructors
explicitly throwing a java.security.SecurityException are likely to have security
issues. From JDK6 on, an exception thrown before the java.lang.Object constructor
exits which prevents the finalizer from being called. Therefore, if subclassing is allowed
and security manager permission is required to construct an object, perform the check
before calling the super constructor. This can be done by inserting a method call as an
argument to an alternative ("this") constructor invocation.
For compatibility with versions of Java prior to JDK 6, check that the class has been
initialized before every sensitive operation and before trusting any other instance of the
class. It may be possible to see a partially initialized instance, so any variable should have a
safe interpretation for the default value. For mutable classes, it is advisable to make an
"initialized" flag volatile to create a suitable happensbefore relationship.
// sole constructor
public NonFinal() {
securityManagerCheck();
When confirming an object's class type by examining the java.lang.Class instance
belonging to that object, do not compare Class instances solely using class names
(acquired via Class.getName), because instances are scoped both by their class name as
well as the class loader that defined the class.
Guideline 46: Understand how a superclass can affect subclass behavior
Subclasses do not have the ability to maintain absolute control over their own behavior. A
superclass can affect subclass behavior by changing the implementation of an inherited
method that is not overridden. If a subclass overrides all inherited methods, a superclass can
still affect subclass behavior by introducing new methods. Such changes to a superclass can
unintentionally break assumptions made in a subclass and lead to subtle security
vulnerabilities. Consider the following example that occurred in JDK 1.2:
The Hashtable class was enhanced in JDK 1.2 to include a new method, entrySet,
which supports the removal of entries from the Hashtable. The Provider class was not
updated to override this new method. This oversight allowed an attacker to bypass the
SecurityManager check enforced in Provider.remove, and to delete Provider
mappings by simply invoking the Hashtable.entrySet method.
The primary flaw is that the data belonging to Provider (its mappings) is stored in the
Hashtable class, whereas the checks that guard the data are enforced in the Provider
class. This separation of data from its corresponding SecurityManager checks only exists
because Provider extends from Hashtable. Because a Provider is not inherently a
Hashtable, it should not extend from Hashtable. Instead, the Provider class should
encapsulate a Hashtable instance allowing the data and the checks that guard that data to
reside in the same class. The original decision to subclass Hashtable likely resulted from
an attempt to achieve code reuse, but it unfortunately led to an awkward relationship
between a superclass and its subclasses, and eventually to a security vulnerability.
Malicious subclasses may implement java.lang.Cloneable. Implementing this interface
affects the behaviour of the subclass. A clone of a victim object may be made. The clone
will be a shallow copy. The intrinsic lock and fields of the two objects will be different, but
referenced objects will be the same. This allows an adversary to confuse the state of
instances of the attacked class.
5. 5 Input Validation
A feature of the culture of Java is that rigorous method parameter checking is used to
improve robustness. More generally, validating external inputs is an important part of
security.
Guideline 51: Validate inputs
Input from untrusted sources must be validated before use. Maliciously crafted inputs may
cause problems, whether coming through method arguments or external streams. Examples
include overflow of integer values and directory traversal attacks by including "../"
sequences in filenames. Easeofuse features should be separated from programmatic
interfaces. Note that input validation must occur after any defensive copying of that input
(see Guideline 62).
Guideline 52: Validate output from untrusted objects as input
In general method arguments should be validated but not return values. However, in the
case of an upcall (invoking a method of higher level code) the returned value should be
validated. Likewise, an object only reachable as an implementation of an upcall need not
validate its inputs.
Guideline 53: Define wrappers around native methods
Java code is subject to runtime checks for type, array bounds, and library usage. Native
code, on the other hand, is generally not. While pure Java code is effectively immune to
traditional buffer overflow attacks, native methods are not. To offer some of these
protections during the invocation of native code, do not declare a native method public.
Instead, declare it private and expose the functionality through a public Javabased wrapper
method. A wrapper can safely perform any necessary input validation prior to the
invocation of the native method:
// validate input
// Note offset+len would be subject to integer overflow.
// For instance if offset = 1 and len = Integer.MAX_VALUE,
// then offset+len == Integer.MIN_VALUE which is lower
// than data.length.
// Further,
// loops of the form
// for (int i=offset; i<offset+len; ++i) { ... }
// would not throw an exception or cause native code to
// crash.
6. 6 Mutability
Mutability, whilst appearing innocuous, can cause a surprising variety of security problems.
Guideline 61: Prefer immutability for value types
Making classes immutable prevents the issues associated with mutable objects (described in
subsequent guidelines) from arising in client code. Immutable classes should not be
subclassable. Further, hiding constructors allows more flexibility in instance creation and
caching. This means making the constructor private or default access ("packageprivate"),
or being in a package controlled by the package.access security property. Immutable
classes themselves should declare fields final and protect against any mutable inputs and
outputs as described in Guideline 62. Construction of immutable objects can be made
easier by providing builders (cf. Effective Java [6]).
Guideline 62: Create copies of mutable output values
If a method returns a reference to an internal mutable object, then client code may modify
the internal state of the instance. Unless the intention is to share state, copy mutable objects
and return the copy.
To create a copy of a trusted mutable object, call a copy constructor or the clone method:
public class CopyOutput {
private final java.util.Date date;
...
public java.util.Date getDate() {
return (java.util.Date)date.clone();
}
}
Guideline 63: Create safe copies of mutable and subclassable input values
Mutable objects may be changed after and even during the execution of a method or
constructor call. Types that can be subclassed may behave incorrectly, inconsistently,
and/or maliciously. If a method is not specified to operate directly on a mutable input
parameter, create a copy of that input and perform the method logic on the copy. In fact, if
the input is stored in a field, the caller can exploit race conditions in the enclosing class. For
example, a timeofcheck, timeofuse inconsistency (TOCTOU) [7] can be exploited
where a mutable input contains one value during a SecurityManager check but a different
value when the input is used later.
To create a copy of an untrusted mutable object, call a copy constructor or creation method:
// java.util.Date is mutable
public CopyMutableInput(Date date) {
// create copy
this.date = new Date(date.getTime());
}
}
In rare cases it may be safe to call a copy method on the instance itself. For instance,
java.net.HttpCookie is mutable but final and provides a public clone method for
acquiring copies of its instances.
// java.net.HttpCookie is mutable
public void copyMutableInput(HttpCookie cookie) {
// create copy
cookie = (HttpCookie)cookie.clone(); // HttpCookie is final
It is safe to call HttpCookie.clone because it cannot be overridden with a malicious
implementation. Date also provides a public clone method, but because the method is
overrideable it can be trusted only if the Date object is from a trusted source. Some classes,
such as java.io.File, are subclassable even though they appear to be immutable.
This guideline does not apply to classes that are designed to wrap a target object. For
instance, java.util.Arrays.asList operates directly on the supplied array without
copying.
In some cases, notably collections, a method may require a deeper copy of an input object
than the one returned via that input's copy constructor or clone method. Instantiating an
ArrayList with a collection, for example, produces a shallow copy of the original
collection instance. Both the copy and the original share references to the same elements. If
the elements are mutable, then a deep copy over the elements is required:
// String is immutable.
public void shallowCopy(Collection<String> strs) {
strs = new ArrayList<String>(strs);
doLogic(strs);
}
// Date is mutable.
public void deepCopy(Collection<Date> dates) {
Collection<Date> datesCopy = new ArrayList<Date>(dates.size());
for (Date date : dates) {
datesCopy.add(new java.util.Date(date.getTime()));
}
doLogic(datesCopy);
}
Constructors should complete the deep copy before assigning values to a field. An object
should never be in a state where it references untrusted data, even briefly. Further, objects
assigned to fields should never have referenced untrusted data due to the dangers of unsafe
publication.
Guideline 64: Support copy functionality for a mutable class
When designing a mutable value class, provide a means to create safe copies of its
instances. This allows instances of that class to be safely passed to or returned from
methods in other classes (see Guideline 62 and Guideline 63). This functionality may be
provided by a static creation method, a copy constructor, or by implementing a public copy
method (for final classes).
If a class is final and does not provide an accessible method for acquiring a copy of it,
callers could resort to performing a manual copy. This involves retrieving state from an
instance of that class and then creating a new instance with the retrieved state. Mutable state
retrieved during this process must likewise be copied if necessary. Performing such a
manual copy can be fragile. If the class evolves to include additional state, then manual
copies may not include that state.
The java.lang.Cloneable mechanism is problematic and should not be used.
Implementing classes must explicitly copy all mutable fields which is highly errorprone.
Copied fields may not be final. The clone object may become available before field
copying has completed, possibly at some intermediate stage. In nonfinal classes
Object.clone will make a new instance of the potentially malicious subclass.
Implementing Cloneable is an implementation detail, but appears in the public interface of
the class.
Guideline 65: Do not trust identity equality when overridable on input reference
objects
Overridable methods may not behave as expected.
If possible, use a collection implementation that enforces identity equality, such as
IdentityHashMap.
If such a collection is not available, use a package private key which an adversary does not
have access to.
Guideline 66: Treat passing input to untrusted object as output
The above guidelines on output objects apply when passed to untrusted objects.
Appropriate copying should be applied.
A common but difficult to spot case occurs when an input object is used as a key. A
collection's use of equality may well expose other elements to a malicious input object on
or after insertion.
Guideline 67: Treat output from untrusted object as input
The above guidelines on input objects apply when returned from untrusted objects.
Appropriate copying and validation should be applied.
Guideline 68: Define wrapper methods around modifiable internal state
If a state that is internal to a class must be publicly accessible and modifiable, declare a
private field and enable access to it via public wrapper methods. If the state is only intended
to be accessed by subclasses, declare a private field and enable access via protected
wrapper methods. Wrapper methods allow input validation to occur prior to the setting of a
new value:
// wrapper method
public String getState() {
return state;
}
// wrapper method
public void setState(final String newState) {
this.state = requireValidation(newState);
}
Make additional defensive copies in getState and setState if the internal state is
mutable, as described in Guideline 62.
Where possible make methods for operations that make sense in the context of the interface
of the class rather than merely exposing internal implementation.
Guideline 69: Make public static fields final
Callers can trivially access and modify public nonfinal static fields. Neither accesses nor
modifications can be guarded against, and newly set values cannot be validated. Fields with
subclassable types may be set to objects with malicious implementations. Always declare
public static fields as final.
If using an interface instead of a class, the " public static final" can be omitted to
improve readability, as the constants are implicitly public, static, and final. Constants can
alternatively be defined using an enum declaration.
Protected static fields suffer from the same problem as their public equivalents but also tend
to indicate confused design.
Guideline 610: Ensure public static final field values are constants
Only immutable values should be stored in public static fields. Many types are mutable and
are easily overlooked, in particular arrays and collections. Mutable objects that are stored in
a field whose type does not have any mutator methods can be cast back to the runtime type.
Enum values should never be mutable.
As per Guideline 610, protected static fields suffer from the same problems astheir public
equivalents.
Guideline 611: Do not expose mutable statics
Private statics are easily exposed through public interfaces, if sometimes only in a limited
way (see Guidelines 62 and 66). Mutable statics may also change behaviour between
unrelated code. To ensure safe code, private statics should be treated as if they are public.
Adding boilerplate to expose statics as singletons does not fix these issues.
Mutable statics may be used as caches of immutable flyweight values. Mutable objects
should never be cached in statics. Even instance pooling of mutable objects should be
treated with extreme caution.
7. 7 Object Construction
During construction objects are at an awkward stage where they exist but are not ready for
use. Such awkwardness presents a few more difficulties in addition to those of ordinary
methods.
Guideline 71: Avoid exposing constructors of sensitive classes
Construction of classes can be more carefully controlled if constructors are not exposed.
Define static factory methods instead of public constructors. Support extensibility through
delegation rather than inheritance. Implicit constructors through serialization and clone
should also be avoided.
Guideline 72: Prevent the unauthorized construction of sensitive classes
Where an existing API exposes a securitysensitive constructor, limit the ability to create
instances. A securitysensitive class enables callers to modify or circumvent
SecurityManager access controls. Any instance of ClassLoader, for example, has the
power to define classes with arbitrary security permissions.
To restrict untrusted code from instantiating a class, enforce a SecurityManager check at all
points where that class can be instantiated. In particular, enforce a check at the beginning of
each public and protected constructor. In classes that declare public static factory methods
in place of constructors, enforce checks at the beginning of each factory method. Also
enforce checks at points where an instance of a class can be created without the use of a
constructor. Specifically, enforce a check inside the readObject or readObjectNoData
method of a serializable class, and inside the clone method of a cloneable class.
If the securitysensitive class is nonfinal, this guideline not only blocks the direct
instantiation of that class, it blocks malicious subclassing as well.
Guideline 73: Defend against partially initialized instances of nonfinal classes
When a constructor in a nonfinal class throws an exception, attackers can attempt to gain
access to partially initialized instances of that class. Ensure that a nonfinal class remains
totally unusable until its constructor completes successfully.
From JDK 6 on, construction of a subclassable class can be prevented by throwing an
exception before the Object constructor completes. To do this, perform the checks in an
expression that is evaluated in a call to this() or super().
// non-final java.lang.ClassLoader
public abstract class ClassLoader {
protected ClassLoader() {
this(securityManagerCheck());
}
private ClassLoader(Void ignored) {
// ... continue initialization ...
}
private static Void securityManagerCheck() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
return null;
}
}
For compatibility with older releases, a potential solution involves the use of an initialized
flag. Set the flag as the last operation in a constructor before returning successfully. All
methods providing a gateway to sensitive operations must first consult the flag before
proceeding:
protected ClassLoader() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
Furthermore, any securitysensitive uses of such classes should check the state of the
initialization flag. In the case of ClassLoader construction, it should check that its parent
class loader is initialized.
Partially initialized instances of a nonfinal class can be accessed via a finalizer attack. The
attacker overrides the protected finalize method in a subclass and attempts to create a
new instance of that subclass. This attempt fails (in the above example, the
SecurityManager check in ClassLoader's constructor throws a security exception), but
the attacker simply ignores any exception and waits for the virtual machine to perform
finalization on the partially initialized object. When that occurs the malicious finalize
method implementation is invoked, giving the attacker access to this, a reference to the
object being finalized. Although the object is only partially initialized, the attacker can still
invoke methods on it, thereby circumventing the SecurityManager check. While the
initialized flag does not prevent access to the partially initialized object, it does prevent
methods on that object from doing anything useful for the attacker.
Use of an initialized flag, while secure, can be cumbersome. Simply ensuring that all fields
in a public nonfinal class contain a safe value (such as null) until object initialization
completes successfully can represent a reasonable alternative in classes that are not security
sensitive.
A more robust, but also more verbose, approach is to use a "pointer to implementation" (or
"pimpl"). The core of the class is moved into a nonpublic class with the interface class
forwarding method calls. Any attempts to use a the class before it is fully initialized will
result in a NullPointerException. This approach is also good for dealing with clone and
deserialization attacks.
public abstract class ClassLoader {
protected ClassLoader() {
this.impl = new ClassLoaderImpl();
}
protected final Class defineClass(...) {
return impl.defineClass(...);
}
}
/* pp */ class ClassLoaderImpl {
/* pp */ ClassLoaderImpl() {
// permission needed to create ClassLoader
securityManagerCheck();
init();
}
/* pp */ Class defineClass(...) {
// regular logic follows
...
}
}
Guideline 74: Prevent constructors from calling methods that can be overridden
Constructors that call overridable methods give attackers a reference to this (the object
being constructed) before the object has been fully initialized. Likewise, clone,
readObject, or readObjectNoData methods that call overridable methods may do the
same. The readObject methods will usually call
java.io.ObjectInputStream.defaultReadObject, which is an overridable method.
Guideline 75: Defend against cloning of nonfinal classes
A nonfinal class may be subclassed by a class that also implements
java.lang.Cloneable. The result is that the base class can be unexpectedly cloned,
although only for instances created by an adversary. The clone will be a shallow copy. The
twins will share referenced objects but have different fields and separate intrinsic locks. The
pointer to implementation approach detailed in Guideline 73 provides a good defence.
8. 8 Serialization and Deserialization
Java Serialization provides an interface to classes that sidesteps the normal expectations of
the Java language.
Guideline 81: Avoid serialization for securitysensitive classes
Securitysensitive classes that are not serializable will not have the problems detailed in this
section. Making a class serializable effectively creates a public interface to all fields of that
class.
Guideline 82: Guard sensitive data during serialization
Once an object has been serialized the Java language's access controls can no longer be
enforced and attackers can access private fields in an object by analyzing its serialized byte
stream. Therefore, do not serialize sensitive data in a serializable class.
Approaches for handling sensitive fields in serializable classes are:
Declare sensitive fields transient
Define the serialPersistentFields array field appropriately
Implement writeObject and use ObjectOutputStream.putField selectively
Implement writeReplace to replace the instance with a serial proxy
Implement the Externalizable interface
Guideline 83: View deserialization the same as object construction
Deserialization creates a new instance of a class without invoking any constructor on that
class. Therefore, deserialization should be designed to behave to match normal
construction.
Perform the same input validation checks in a readObject method implementation as
those performed in a constructor. Likewise, assign default values that are consistent with
those assigned in a constructor to all fields, including transient fields, which are not
explicitly set during deserialization.
In addition create copies of deserialized mutable objects before assigning them to internal
fields in a readObject implementation. This defends against hostile code deserializing
byte streams that are specially crafted to give the attacker references to mutable objects
inside the deserialized container object.
Attackers can also craft hostile streams in an attempt to exploit partially initialized
(deserialized) objects. Ensure a serializable class remains totally unusable until
deserialization completes successfully. For example, use an initialized flag. Declare the
flag as a private transient field and only set it in a readObject or readObjectNoData
method (and in constructors) just prior to returning successfully. All public and protected
methods in the class must consult the initialized flag before proceeding with their
normal logic. As discussed earlier, use of an initialized flag can be cumbersome.
Simply ensuring that all fields contain a safe value (such as null) until deserialization
successfully completes can represent a reasonable alternative.
Guideline 84: Duplicate the SecurityManager checks enforced in a class during
serialization and deserialization
Prevent an attacker from using serialization or deserialization to bypass the
SecurityManager checks enforced in a class. Specifically, if a serializable class enforces a
SecurityManager check in its constructors, then enforce that same check in a readObject
or readObjectNoData method implementation. Otherwise an instance of the class can be
created without any check via deserialization.
If a serializable class enables internal state to be modified by a caller (via a public method,
for example) and the modification is guarded with a SecurityManager check, then
enforce that same check in a readObject method implementation. Otherwise, an attacker
can use deserialization to create another instance of an object with modified state without
passing the check.
public SecureName() {
// initialize name to default value
name = DEFAULT;
}
inputValidation(name);
this.name = name;
}
}
if (!DEFAULT.equals(name)) {
securityManagerCheck();
inputValidation(name);
}
this.name = name;
}
If a serializable class enables internal state to be retrieved by a caller and the retrieval is
guarded with a SecurityManager check to prevent disclosure of sensitive data, then enforce
that same check in a writeObject method implementation. Otherwise, an attacker can
serialize an object to bypass the check and access the internal state simply by reading the
serialized byte stream.
return value;
}
Permissions appropriate for deserialization should be carefully checked.
9. 9 Access Control
Although Java is largely an objectcapability language, a stackbased access control
mechanism is used to securely provide more conventional APIs.
Guideline 91: Understand how permissions are checked
The standard security check ensures that each frame in the call stack has the required
permission. That is, the current permissions in force is the intersection of the permissions of
each frame in the current access control context. If any frame does not have a permission,
no matter where it lies in the stack, then the current context does not have that permission.
Consider an application that indirectly uses secure operations through a library.
package xx.lib;
package yy.app;
class AppClass {
public static void main(String[] args) {
System.out.println(
xx.lib.LibClass.getOptions()
);
}
}
When the permission check is performed, the call stack will be as illustrated below.
+--------------------------------+
| java.security.AccessController |
| .checkPermission(Permission) |
+--------------------------------+
| java.lang.SecurityManager |
| .checkPermission(Permission) |
+--------------------------------+
| java.lang.SecurityManager |
| .checkPropertyAccess(String) |
+--------------------------------+
| java.lang.System |
| .getProperty(String) |
+--------------------------------+
| xx.lib.LibClass |
| .getOptions() |
+--------------------------------+
| yy.app.AppClass |
| .main(String[]) |
+--------------------------------+
In the above example, if the AppClass frame does not have permission to read a file but
the LibClass frame does, then a security exception is still thrown. It does not matter that
the immediate caller of the privileged operation is fully privileged, but that there is
unprivileged code on the stack somewhere.
For library code to appear transparent to applications with respect to privileges, libraries
should be granted permissions at least as generous as the application code that it is used
with. For this reason, almost all the code shipped in the JDK and extensions is fully
privileged. It is therefore important that there be at least one frame with the application's
permissions on the stack whenever a library executes security checked operations on behalf
of application code.
Guideline 92: Beware of callback methods
Callback methods are generally invoked from the system with full permissions. It seems
reasonable to expect that malicious code needs to be on the stack in order to perform an
operation, but that is not the case. Malicious code may set up objects that bridge the
callback to a security checked operation. For instance, a file chooser dialog box that can
manipulate the filesystem from user actions, may have events posted from malicious code.
Alternatively, malicious code can disguise a file chooser as something benign while
redirecting user events.
Callbacks are widespread in objectoriented systems. Examples include the following:
Static initialization is often done with full privileges
Application main method
Applet/Midlet/Servlet lifecycle events
Runnable.run
This bridging between callback and securitysensitive operations is particularly tricky
because it is not easy to spot the bug or to work out where it is.
When implementing callback types, use the technique described in Guideline 96 to transfer
context. For instance, java.beans.EventHandler is a dynamic proxy that may be used to
implement callback interfaces. EventHandler captures the context when it is constructed
and uses that to execute the target operation. This means that instances of EventHandler
may well be securitysensitive.
Guideline 93: Safely invoke java.security.AccessController.doPrivileged
+--------------------------------+
| action |
| .run |
+--------------------------------+
| java.security.AccessController |
| .doPrivileged |
+--------------------------------+
| SomeClass |
| .someMethod |
+--------------------------------+
| OtherClass |
| .otherMethod |
+--------------------------------+
| |
In the above example, the privileges of the OtherClass frame are ignored for security
checks.
To avoid inadvertently performing such operations on behalf of unauthorized callers, be
very careful when invoking doPrivileged using callerprovided inputs (tainted inputs):
package xx.lib;
import java.security.*;
The implementation of getOptions properly retrieves the system property using a
hardcoded value. More specifically, it does not allow the caller to influence the name of the
property by passing a callerprovided (tainted) input to doPrivileged.
Caller inputs that have been validated can sometimes be safely used with doPrivileged.
Typically the inputs must be restricted to a limited set of acceptable (usually hardcoded)
values.
Privileged code sections should be made as small as practical in order to make
comprehension of the security implications tractable.
The twoargument overloads of doPrivileged allow changing of privileges to that of a
previous acquired context. A null context is interpreted as adding no further restrictions.
Therefore, before using stored contexts, make sure that they are not null
( AccessController.getContext never returns null).
if (acc == null) {
throw new SecurityException("Missing AccessControlContext");
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
...
}
}, acc);
Guideline 94: Know how to restrict privileges through doPrivileged
As permissions are restricted to the intersection of frames, an artificial
AccessControlContext representing no (zero) frames implies all permissions. The
following three calls to doPrivileged are equivalent:
All permissions can be removed using an artificial AccessControlContext context
containing a frame of a ProtectionDomain with no permissions:
+--------------------------------+
| ActionImpl |
| .run |
+--------------------------------+
| |
| noPermissionsAcc |
+ - - - - - - - - - - - - - - - -+
| java.security.AccessController |
| .doPrivileged |
+--------------------------------+
| SomeClass |
| .someMethod |
+--------------------------------+
| OtherClass |
| .otherMethod |
+--------------------------------+
| |
An intermediate situation is possible where only a limited set of permissions is granted. If
the permissions are checked in the current context before being supplied to doPrivileged,
permissions may be reduced without the risk of privilege elevation. This enables the use of
the principle of least privilege:
Guideline 95: Be careful caching results of potentially privileged operations
A cached result must never be passed to a context that does not have the relevant
permissions to generate it. Therefore, ensure that the result is generated in a context that has
no more permissions than any context it is returned to. Because calculation of privileges
may contain errors, use the AccessController API to enforce the constraint.
return value;
}
Guideline 96: Understand how to transfer context
It is often useful to store an access control context for later use. For example, one may
decide it is appropriate to provide access to callback instances that perform privileged
operations, but invoke callback methods in the context that the callback object was
registered. The context may be restored later on in the same thread or in a different thread.
A particular context may be restored multiple times and even after the original thread has
exited.
AccessController.getContext returns the current context. The twoargument forms of
AccessController.doPrivileged can then replace the current context with the stored
context for the duration of an action.
package xx.lib;
+--------------------------------+
| xx.lib.FileHandler |
| handle() |
+--------------------------------+
| xx.lib.Reactor.(anonymous) |
| run() |
+--------------------------------+ \ +--------------------------------+
| java.security.AccessController | ` | |
| .getContext() | +--> | acc |
+--------------------------------+ | + - - - - - - - - - - - - - - - -+
| xx.lib.Reactor | | | java.security.AccessController |
| .addHandler(Handler) | | | .doPrivileged(handler, acc) |
+--------------------------------+ | +--------------------------------+
| yy.app.App | | | xx.lib.Reactor |
| .main(String[] args) | , | .fire |
+--------------------------------+ / +--------------------------------+
| xx.lib.Reactor |
| .run |
+--------------------------------+
| |
Guideline 97: Understand how thread construction transfers context
Newly constructed threads are executed with the access control context that was present
when the Thread object was constructed. In order to prevent bypassing this context, `void
run()` of untrusted objects should not be executed with inappropriate privileges.
Guideline 98: Safely invoke standard APIs that bypass SecurityManager checks
depending on the immediate caller's class loader
Certain standard APIs in the core libraries of the Java runtime enforce SecurityManager
checks but allow those checks to be bypassed depending on the immediate caller's class
loader. When the java.lang.Class.newInstance method is invoked on a Class object,
for example, the immediate caller's class loader is compared to the Class object's class
loader. If the caller's class loader is an ancestor of (or the same as) the Class object's class
loader, the newInstance method bypasses a SecurityManager check. (See Section 4.3.2 in
[1] for information on class loader relationships). Otherwise, the relevant SecurityManager
check is enforced.
The difference between this class loader comparison and a SecurityManager check is
noteworthy. A SecurityManager check investigates all callers in the current execution chain
to ensure each has been granted the requisite security permission. (If
AccessController.doPrivileged was invoked in the chain, all callers leading back to
the caller of doPrivileged are checked.) In contrast, the class loader comparison only
investigates the immediate caller's context (its class loader). This means any caller who
invokes Class.newInstance and who has the capability to pass the class loader check
thereby bypassing the SecurityManagereffectively performs the invocation inside an
implicit AccessController.doPrivileged action. Because of this subtlety, callers
should ensure that they do not inadvertently invoke Class.newInstance on behalf of
untrusted code.
package yy.app;
class AppClass {
OtherClass appMethod() throws Exception {
return OtherClass.class.newInstance();
}
}
+--------------------------------+
| xx.lib.LibClass |
| .LibClass |
+--------------------------------+
| java.lang.Class |
| .newInstance |
+--------------------------------+
| yy.app.AppClass |<-- AppClass.class.getClassLoader
| .appMethod | determines check
+--------------------------------+
| |
Code has full access to its own class loader and any class loader that is a descendent. In the
case of Class.newInstance access to a class loader implies access to classes in restricted
packages (e.g., sun.* in the Sun JDK).
In the diagram below, classes loaded by B have access to B and its descendents C, E, and
F. Other class loaders, shown in grey strikeout font, are subject to security checks.
+-------------------------+
| extension loader | | A |
+------------------+ +---+
^
+------------------+
| B | |F|
+----------+ +---+
^ ^ ^
The following methods behave similar to Class.newInstance, and potentially bypass
SecurityManager checks depending on the immediate caller's class loader:
java.lang.Class.newInstance
java.lang.Class.getClassLoader
java.lang.Class.getClasses
java.lang.Class.getField(s)
java.lang.Class.getMethod(s)
java.lang.Class.getConstructor(s)
java.lang.Class.getDeclaredClasses
java.lang.Class.getDeclaredField(s)
java.lang.Class.getDeclaredMethod(s)
java.lang.Class.getDeclaredConstructor(s)
java.lang.ClassLoader.getParent
java.lang.ClassLoader.getSystemClassLoader
java.lang.Thread.getContextClassLoader
Refrain from invoking the above methods on Class, ClassLoader, or Thread instances that
are received from untrusted code. If the respective instances were acquired safely (or in the
case of the static ClassLoader.getSystemClassLoader method), do not invoke the
above methods using inputs provided by untrusted code. Also, do not propagate objects
that are returned by the above methods back to untrusted code.
Guideline 99: Safely invoke standard APIs that perform tasks using the immediate
caller's class loader instance
The following static methods perform tasks using the immediate caller's class loader:
java.lang.Class.forName
java.lang.Package.getPackage(s)
java.lang.Runtime.load
java.lang.Runtime.loadLibrary
java.lang.System.load
java.lang.System.loadLibrary
java.sql.DriverManager.getConnection
java.sql.DriverManager.getDriver(s)
java.sql.DriverManager.deregisterDriver
java.util.ResourceBundle.getBundle
For example, System.loadLibrary("/com/foo/MyLib.so") uses the immediate caller's
class loader to find and load the specified library. (Loading libraries enables a caller to
make native method invocations.) Do not invoke this method on behalf of untrusted code,
since untrusted code may not have the ability to load the same library using its own class
loader instance. Do not invoke any of these methods using inputs provided by untrusted
code, and do not propagate objects that are returned by these methods back to untrusted
code.
Guideline 910: Be aware of standard APIs that perform Java language access
checks against the immediate caller
When an object accesses fields or methods in another object, the virtual machine
automatically performs language access checks. For example, it prevents objects from
invoking private methods in other objects.
Code may also call standard APIs (primarily in the java.lang.reflect package) to
reflectively access fields or methods in another object. The following reflectionbased APIs
mirror the language checks that are enforced by the virtual machine:
java.lang.Class.newInstance
java.lang.reflect.Constructor.newInstance
java.lang.reflect.Field.get*
java.lang.reflect.Field.set*
java.lang.reflect.Method.invoke
java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater
java.util.concurrent.atomic.AtomicLongFieldUpdater.newUpdater
java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater
Language checks are performed solely against the immediate caller, not against each caller
in the execution sequence. Because the immediate caller may have capabilities that other
code lacks (it may belong to a particular package and therefore have access to its package
private members), do not invoke the above APIs on behalf of untrusted code. Specifically,
do not invoke the above methods on Class, Constructor, Field, or Method instances
that are received from untrusted code. If the respective instances were acquired safely, do
not invoke the above methods using inputs that are provided by untrusted code. Also, do
not propagate objects that are returned by the above methods back to untrusted code.
The java.beans package provides safe alternatives to some of these methods.
Guideline 911: Be aware java.lang.reflect.Method.invoke is ignored for
checking the immediate caller
Consider:
package xx.lib;
class LibClass {
void libMethod(
PrivilegedAction action
) throws Exception {
Method doPrivilegedMethod =
AccessController.class.getMethod(
"doPrivileged", PrivilegedAction.class
);
doPrivilegedMethod.invoke(null, action);
}
}
If Method.invoke was taken as the immediate caller, then the action would be performed
with all permissions. So, for the methods discussed in Guidelines 98 through 910, the
Method.invoke implementation is ignored when determining the immediate caller.
+--------------------------------+
| action |
| .run |
+--------------------------------+
| java.security.AccessController |
| .doPrivileged |
+--------------------------------+
| java.lang.reflect.Method |
| .invoke |
+--------------------------------+
| xx.lib.LibClass | <--- Effective caller
| .libMethod |
+--------------------------------+
| |
10. Conclusion
The Java Platform provides a robust basis for secure systems through features such as
memorysafety. However, the platform alone cannot prevent flaws being introduced. This
document details many of the common pitfalls. The most effective approach to minimizing
vulnerabilities is to have obviously no flaws rather than no obvious flaws.
11. References
1. Li Gong, Gary Ellison, and Mary Dageforde. Inside Java 2 Platform Security. 2nd
ed. Boston, MA: AddisonWesley, 2003.
2. James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java Language
Specification. 3rd ed. Boston, MA: AddisonWesley, 2005.
3. Tim Lindholm and Frank Yellin. The Java Virtual Machine Specification. 2nd ed.
Reading, MA: AddisonWesley, 1999.
4. Aleph One. Smashing the Stack for Fun and Profit. Phrack 49, November 1996.
5. John Viega and Gary McGraw. Building Secure Software: How to Avoid Security
Problems the Right Way. Boston: AddisonWesley, 2002.
6. Joshua Bloch. Effective Java Programming Language Guide. 2nd ed. Addison
Wesley Professional, 2008.
7. Gary McGraw. Software Security: Building Security In. Boston: AddisonWesley,
2006.
8. C.A.R. Hoare. The Emperor's Old Clothes. Communications of the ACM, 1981
From oracle.com 2013?