The application of the secure coding standard leads to higher quality systems that are The CERT Oracle Secure Coding Standard for Java focuses on the Java. Contribute to nvtuongcs/Ebook development by creating an account on GitHub. The CERT Oracle secure coding standard for Java / Fred Long [et al.]. p. cm. —(The SEI series in software engineering). Includes bibliographical references.
|Language:||English, Spanish, German|
|Distribution:||Free* [*Registration Required]|
“In the Java world, security is not viewed as an add-on a feature. It is a pervasive way of thinking. Those who forget to think in a secure mindset end up in trouble. The Java rules and recommendations in this wiki are a work in progress and reflect the current thinking of the secure coding community. Because this is a. Abstract. This is the first authoritative, comprehensive compilation of code-level requirements for building secure systems in Java. Organized by CERT's.
Trust boundaries are also necessary to allow security audits 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? SecurityManager checks should be considered a last resort.
Perform security checks at a few defined points and return an object a capability that client code retains so that no further permission checks are required. Note, however, that care must be taken by both the code performing the check and the caller to prevent the capability from being leaked to code without the proper permissions. See Section 9 for additional information. 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.
Documenting this information in comments for a tool such as Javadoc can also help to ensure that it is kept up to date. 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.
In addition to attacks that cause excessive resource consumption, attacks that result in persistent DoS, such as wasting significant disk space, need be defended against. Server systems should be especially robust against external attacks. 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.
When decompressing files, it is better to set limits on the decompressed data size rather than relying upon compressed size or meta-data. Set the XMLConstants. 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. 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. It is easy to overlook the vast possibilities for executions paths when exceptions are thrown. Resources should always be released promptly no matter what. Even experienced programmers often handle resources incorrectly. In order to reduce errors, duplication should be minimized and resource handling concerns should be separated.
The Execute Around Method pattern provides an excellent way of extracting the paired acquire and release operations.
The pattern can be used concisely using the Java SE 8 lambda feature. Attempts to rearrange this idiom typically result in errors and makes the code significantly harder to follow. If the flush fails, the code should exit via an exception. For instance, in the current Oracle JDK implementation compression-related streams are natively implemented using the C heap for buffer storage.
Care must be taken that both resources are released in all circumstances. For example, code inside of the try statement could indefinitely block while attempting to access a resource. If the try statement calls into untrusted code, that code could also intentionally sleep or block in order to prevent the cleanup code from being reached.
As a result, resources used in a try-with-resources statement may not be closed, or code in a finally block may never be executed in these situations. However, some operations on primitive integral 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. So, Integer.
The same edge case occurs for Long. As of Java SE 8, the java. Math class also contains methods for various operations addExact, multiplyExact, decrementExact, etc. Data that is to be trusted should not be exposed to tampering.
Privileged code should not be executable through intended interfaces. For example, if a method calls the java. FileInputStream constructor to read an underlying configuration file and that file is not present, a java. 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. 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 sometimes also necessary to sanitize exceptions containing information derived from caller inputs.
For example, exceptions related to file access could disclose whether a file exists. An attacker may be able to gather useful information by providing various file names as input and analyzing the resulting exceptions. 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. 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 lower-level 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. 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.
Typically, but not always, this involves text formats. 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 error-prone.
Parsing and canonicalization should be done before validation. If possible, reject invalid data and any subsequent data, without attempting correction.
Use well-tested libraries instead of ad hoc code. There are many libraries for creating XML. Creating XML documents using raw text is error-prone.
For unusual formats where appropriate libraries do not exist, such as configuration files, create classes that cleanly handle all formatting and only formatting code.
This often takes the form of supplying an input containing a quote character ' followed by SQL. Avoid dynamic SQL. PreparedStatement or java. CallableStatement instead of java. In general, it is better to use a well-written, higher-level library to insulate application code from SQL. When using such a library, it is not necessary to limit characters such as quote '.
There are many different ways to sanitize data before including it in output. Characters that are problematic for the specific type of output can be filtered, escaped, or encoded. Alternatively, characters that are known to be safe can be allowed, and everything else can be filtered, escaped, or encoded.
This latter approach is preferable, as it does not require identifying and enumerating all characters that could potentially cause problems. Implementing correct data sanitization and encoding can be tricky and error-prone. Behavior is platform-specific, poorly documented, and frequently surprising. Any data that needs to be passed to the new process should be passed either as encoded arguments e. The safest way to avoid these problems while maintaining the power of XML is to reduce privileges as described in Guideline and to use the most restrictive configuration possible for the XML parser.
Reducing privileges still allows you to grant some access, such as inclusion to pages from the same-origin web site if necessary. XML parsers can also be configured to limit functionality based on what is required, such as disallowing external entities or disabling DTDs altogether. 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 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. TRUE no other Boolean true instance will do. If the source is not trusted to supply code, then a secure sandbox must be constructed to run it in.
RMI may allow loading of remote code specified by remote connection. On the Oracle JDK, this is disabled by default but may be enabled or disabled through the java. On the Oracle JDK, this is disabled by default but may be enabled or disabled through the com. Many SQL implementations allow execution of code with effects outside of the database itself. Unfortunately the processing of exceptional values is typically not immediately noticed without introducing sanitization code.
Moreover, passing an exceptional value to an operation propagates the exceptional numeric state to the operation result. Both positive and negative infinity values are possible outcomes of a floating point operation  , when results become too high or too low to be representable by the memory area that backs a primitive floating point value. Also, the exceptional value NaN can result from dividing 0. The results of casting propagated exceptional floating point numbers to short, integer and long primitive values need special care, too.
This is because an integer conversion of a NaN value will result in a 0, and a positive infinite value is transformed to Integer. There are distinct application scenarios where these exceptional values are expected, such as scientific data analysis which relies on numeric processing. However, it is advised that the result values be contained for that purpose in the local component. This can be achieved by sanitizing any floating point results before passing them back to the generic parts of an application.
As mentioned before, the programmer may wish to include sanitization code for these exceptional values when working with floating point numbers, especially if related to authorization or authentication decisions, or forwarding floating point values to JNI. The Double and Float classes help with sanitization by providing the isNan and isInfinite methods.
Also keep in mind that comparing instances of Double.
NaN via the equality operator always results to be false, which may cause lookup problems in maps or collections when using the equality operator on a wrapped double field within the equals method in a class definition. A typical code pattern that can block further processing of unexpected floating point numbers is shown in the following example snippet. Declare any class or interface public if it is specified as part of a published API, otherwise, declare it package-private. 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 package-private to avoid exposing the implementation. Note that members of interfaces are implicitly public. Classes loaded by different loaders do not have package-private 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. 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. Note that it is not thread-safe. This code should generally only appear once in a system. 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.
Although there may be security checks on direct accesses, there are indirect ways of using the system class loader and thread context class loader. Programs should be written with the expectation that the system class loader is accessible everywhere and the thread context class loader is accessible to all code that can execute on the relevant threads. 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. 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 and exceptions are common ways that isolation is inadvertently breached. Mutable statics allow any code to interfere with code that directly or, more likely, indirectly uses them. Library code can be carefully written such that it is safely usable by less trusted code. Libraries require a level of trust at least equal to the code it is used by in order not to violate the integrity of the client code.
Containers should ensure that less trusted code is not able to replace more trusted library code and does not have package-private access. Both restrictions are typically enforced by using a separate class loader instance, the library class loader a parent of the application class loader. Assertion status may be turned on and off. The instance may be cast to a subclass. ClassLoader subclasses frequently have undesirable methods. Guideline explains access checks made on acquiring ClassLoader instances through various Java library methods.
Care should be taken when exposing a class loader through the thread context class loader. Left non-final, 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. Low-level classes with constructors explicitly throwing a java. SecurityException are likely to have security issues. From JDK6 on, an exception thrown before the java. 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. 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 happens-before relationship.
Class instance belonging to that object, do not compare Class instances solely using class names acquired via Class. 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. Provider extends from java. Properties, and Properties extends from java. In this hierarchy, the Provider class inherits certain methods from Hashtable, including put and remove. To prevent malicious code from affecting its internal mappings, Provider overrides put and remove to enforce the necessary SecurityManager checks.
The Hashtable class was enhanced in JDK 1. The Provider class was not updated to override this new method. This oversight allowed an attacker to bypass the SecurityManager check enforced in Provider. 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. Implementing this interface affects the behavior of the subclass. A clone of a victim object may be made. The clone will be a shallow copy. They show how to produce programs that are not only secure, but also safer, more reliable, more robust, and easier to maintain.
After a high-level introduction to Java application security, eighteen consistently organized chapters detail specific guidelines for each facet of Java development. Each set of guidelines defines conformance, presents both non-compliant examples and corresponding compliant solutions, shows how to assess risk, and offers references for further information.
To limit this book's size, the authors focus on "normative requirements": A follow-up book will present "non-normative requirements": Ask a question about this Book. Available at InformIT.
Menu About About back. Research and Capabilities back. Publications back. News and Events back. Education and Outreach back.