top of page
Search

Effective Java 3rd Edition PDF 22: The Ultimate Resource for Java Developers

  • gardner-sebastian1
  • Aug 20, 2023
  • 6 min read


The Java security mechanism can also be used to implement the principle of least privilege, although it does not provide protection as strong as lower-level mechanisms. 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 9). Note that when taking this approach, the security manager should be installed as early as possible (ideally from the command-line). Delaying installation may result in security-sensitive operations being performed before the security manager is in place, which could reduce the effectiveness of security checks or cause objects to be created with excessive permissions.




effective java 3rd edition pdf 22




The checkIndex, checkFromToIndex, and checkFromIndexSize methods from the java.util.Objects class (available in Java 9 and later) can also be used to avoid integer overflows when performing range and bounds checks. These methods throw an IndexOutOfBoundsException if the index or sub-range being checked is out of bounds. The following code from java.io.OutputStream demonstrates this:


As of Java SE 8, the java.lang.Math class also contains methods for various operations (addExact, multiplyExact, decrementExact, etc.) that throw an ArithmeticException if the result overflows the given type.


The Java platform provides mechanisms to handle exceptions effectively, such as the try-catch-finally statement of the Java programming language, and, as a last resort, the Thread.UncaughtExceptionHandler mechanism for consistent handling of uncaught exceptions across a framework. Secure systems need to make effective use of these mechanisms in order to achieve their desired quality, security, and robustness goals. It is important for applications to minimize exceptions by utilizing robust resource management, and also by eliminating bugs that could result in exceptions being thrown. However, since exceptions may also be thrown due to unforeseeable or unavoidable conditions, secure systems must also be able to safely handle exceptions whenever possible.


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.


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.


For parameterized 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 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 ('). If text destined for XML/HTML is handled correctly during output (Guideline 3-3), then it is unnecessary to disallow characters such as less than (


Some apparently global objects are actually local to applet1 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.


Malicious subclasses that override the Object.finalize2 method can resurrect objects even if an exception was thrown from the constructor. Low-level 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 checks must be performed 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.


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.


The class java.security.Provider extends from java.util.Properties, and Properties extends from java.util.Hashtable. In this hierarchy, the Provider class inherits certain methods from Hashtable, including put and remove. Provider.put maps a cryptographic algorithm name, like RSA, to a class that implements that algorithm. To prevent malicious code from affecting its internal mappings, Provider overrides put and remove to enforce the necessary SecurityManager checks.


Malicious subclasses may implement java.lang.Cloneable. 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. 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.


It may also be necessary to perform validation on input more than once. Performing validation early can be beneficial, as it will reject invalid input sooner and reduce exposure to malformed data. However, validating the input immediately prior to using it for a security-sensitive task will cover any modifications made since it was previously validated, and also allows for validation to be more specific to the context of its use. Earlier validation may not be effective for the current task, as it could have been performed by another part of the application or system, using different assumptions about the context or intended use of the input.


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 Java-based wrapper method. A wrapper can safely perform any necessary input validation prior to the invocation of the native method:


The examples in this section use java.util.Date extensively as it is an example of a mutable API class. In an application, it would be preferable to use the new Java Date and Time API (java.time.*) which has been designed to be immutable.


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.


It is safe to call HttpCookie.clone because it cannot be overridden with an unsafe or 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.


The java.lang.Cloneable mechanism is problematic and should not be used. Implementing classes must explicitly copy all mutable fields which is highly error-prone. Copied fields may not be final. The clone object may become available before field copying has completed, possibly at some intermediate stage. In non-final classes Object.clone will make a new instance of the potentially unsafe or malicious subclass. Implementing Cloneable is an implementation detail, but appears in the public interface of the class.


Note that the of/ofEntries API methods return an unmodifiable collection, whereas the Collections.unmodifiable... API methods (unmodifiableCollection(), unmodifiableList(), unmodifiableMap(), etc.) return an unmodifiable view to a collection. While the collection cannot be modified via the unmodifiable view, the underlying collection may still be modified via a direct reference to it. However, the collections returned by the of/ofEntries API methods are in fact unmodifiable. See the java.util.Collections API documentation for a complete list of methods that return unmodifiable views to collections.


Arrays exposed via public variables or get methods can introduce similar issues. For those cases, a copy of the internal array (created using clone(), java.util.Arrays.copyOf(), etc.) should be exposed instead. java.util.Arrays.asList() should not be used for exposing an internal array, as this method creates a copy backed by the array, allowing two-way modification of the contents.


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. 2ff7e9595c


 
 
 

Recent Posts

See All

Kommentare


© 2023 by Anim8. Proudly created with Wix.com

  • Facebook Globe
  • Twitter Globe
bottom of page