The Java programming language and runtime system were designed with security in mind. For example, pointer manipulation is implicit and hidden from the programmer, and any attempt to reference a null pointer results in an exception being thrown. Similarly, an exception results from any attempt to access an array or a string outside of its bounds. Java is a strongly typed language, and all implicit type conversions are well defined and platform independent, as are the arithmetic types and conversions. The Java Virtual Machine (JVM) has a built-in bytecode verifier to ensure that the bytecode being run conforms to the Java™ Language Specification: Java SE 7 Edition (JLS) so that all the checks defined in the language are in place and cannot be circumvented.

The Java class loader mechanism identifies classes as they are loaded into the JVM and can distinguish between trusted system classes and other classes that may not be trusted. Classes from external sources can be given privileges by digitally signing them; these digital signatures can also be examined by the class loader, and contribute to the class’s identification. Java also provides an extensible fine-grained security mechanism that enables the programmer to control access to resources such as system information, files, sockets, and any other security-sensitive resources that the programmer wishes to use. This security mechanism can require that a runtime security manager be in place to enforce a security policy. A security manager and its security policy are usually specified by command-line arguments, but they may be installed programmatically, provided that such an action is not already disallowed by an existing security policy. Privileges to access resources may be extended to nonsystem Java classes by relying on the identification provided by the class loader mechanism.

Enterprise Java applications are susceptible to attacks because they accept untrusted input and interact with complex subsystems. Injection attacks (such as cross-site scripting [XSS], XPath, and LDAP injection) are possible when the components susceptible to these attacks are used in the application. An effective mitigation strategy is to whitelist input and encode or escape output before it is processed for rendering.

This chapter contains guidelines that are concerned specifically with ensuring the security of Java-based applications. Guidelines dealing with the following security nuances are articulated:

  1. Dealing with sensitive data
  2.  Avoiding common injection attacks
  3. Language features that can be misused to compromise security
  4. Details of Java’s fine-grained security mechanism

01. Limit the lifetime of sensitive data
02. Do not store unencrypted sensitive information on the client side
03. Provide sensitive mutable classes with unmodifiable wrappers
04. Ensure that security-sensitive methods are called with validated arguments
05. Prevent arbitrary file upload
06. Properly encode or escape output
07. Prevent code injection
08. Prevent XPath Injection
09. Prevent LDAP injection
10. Do not use the clone method to copy untrusted method parameters
11. Do not use Object.equals() to compare cryptographic keys
12. Do not use insecure or weak cryptographic algorithms
13. Store passwords using a hash function
14. Ensure that SecureRandom is properly seeded
15. Do not rely on methods that can be overridden by untrusted code
16. Avoid granting excess privileges
17. Minimize privileged code
18. Do not expose methods that use reduced-security checks to untrusted code
19. Define custom security permissions for fine-grained security
20. Create a secure sandbox using a security manager
21. Do not let untrusted code misuse privileges of callback methods