Every Java developer should follow coding standards and best practices to develop secure Java code. It is critical your code is not vulnerable to exploits or malicious attacks. In recent times, even big organizations like eBay, the CIA, and the IRS have fallen victim to vulnerabilities in their applications that have been discovered and exploited by attackers.
The following guidelines provide a solid foundation for writing secure Java code and applications. These will minimize the possibility of creating security vulnerabilities caused by Java developers and help prevent known malicious attacks.
1. Only Use Tried and Tested Libraries
A large percentage of the code in applications is sourced from public libraries and frameworks. These libraries can contain vulnerabilities that may allow a malicious attacker to exploit your application.
Organizations trust their business and reputation to the libraries they use, so make sure you only use proven ones and keep them up to date with the latest versions. Consider checking if they have any known vulnerabilities or require any security fixes.
2. Avoid Serialization
Java serialization is inherently insecure which is why Oracle recently announced it has a long-term plan to remove it. Serialization vulnerabilities were recently found in Cisco and Jenkins applications.
Any application that accepts serialized Java objects is vulnerable, even if a library or framework is responsible and not your own Java code. One area to watch out for is making an interface serializable without thinking through what could be exposed. Another pitfall to avoid is accidentally making a security-sensitive class serializable, either by subclassing or implementing a serializable interface.
3. Always Hash User Passwords
Never store any passwords as plain text. Always hash user passwords preferably using a salted hash and a recommended hashing algorithm like SHA-2. When a password has been ‘hashed’, it has been turned into a scrambled version of itself. Using a predefined key known to the application, the hash value is derived from a combination of both the password and the key using a hashing algorithm.
4. Filter Sensitive Information From Exceptions
Exception objects can contain sensitive information that can assist an attacker hoping to exploit your system. An attacker can manufacture input arguments to expose internal structures and mechanisms of the application. It’s important to remember that information can be leaked from the exception message text and the type of an exception.
Take for example the FileNotFoundException message. These messages contain information about the layout of the file system and the exception type reveals the missing requested file.
To secure Java code applications, you should filter both exception messages and exception type.
5. Do Not Log Sensitive Information
Data thefts cause massive harm to individuals and organizations, and developers need to do everything possible to prevent them from happening. Information like credit and debit card numbers, bank account numbers, passport numbers, and passwords are highly sensitive and valuable to criminals. Don’t store this type of information in log files and make sure it’s not detectable through searches in cleartext.
If you have to log any sensitive information like card numbers, for example, think about logging only part of the card number e.g. the last four digits, and make sure it’s encrypted using a proven library. Don’t write your own encryption functionality.
6. Error Handling and Logging
You can accidentally reveal sensitive information in user error messages and error messages recorded in the log files, such as account information or system details.
A safer way is to use generic screen error messages for users. Additionally, write log error messages that will help support teams investigating production issues without providing an attacker with useful information to further exploit your systems.
7. Write Simple Java Code
Generally speaking, simple java code is secure java code. Here are some tips on keeping your code simple and secure:
- Keep it as simple as possible without reducing functionality.
- Use code quality checking products like SonarQube. This tool will continuously inspect the code quality whilst checking for any new vulnerabilities in your latest code release. Once a bug or vulnerability is in production, it is a lot harder to fix it compared to the effort to prevent it in the first place.
- Expose the minimum amount of information in your code. Hiding implementation details is good for keeping your code both secure and maintainable.
- Make good use of Java’s access modifiers. Declare the most restrictive access levels for classes, methods, and their attributes possible. Set everything that can be set to private, as private.
- Always define the smallest possible API and interface objects. Decouple components and make them interact in the smallest scope possible. If one component of your application is compromised by a breach, the others will be safe.
8. Prevent Injection Attacks
An injection attack occurs when malicious code is injected into the network. This type of attack is considered a major problem in web application security and is listed as the number one security risk in the OWASP Top 10. Any application that allows users to enter or upload data might contain a vulnerability that can allow an injection attack. Insufficient user input validation is usually the primary reason injection vulnerabilities exist.
SQL Injection vulnerabilities are created when developers write dynamic database queries that can include user input. An attacker can include SQL commands in the input data, in any screen input field. Then because of a vulnerability in the code, the application runs the rogue SQL in the database. This gives attackers a way to bypass the application’s authentication functionality and allow them to retrieve the contents of an entire database.
Key things to remember to prevent SQL injections:
- Never build SQL statements by concatenating arguments. This allows a high probability of SQL injection attacks.
- Avoid dynamic SQL. Use Prepared Statements (with parameterized queries).
- Use stored procedures.
- Whitelist input validation.
- Escape user-supplied input.
XPath injections are similar to SQL injections in that they can attack websites that operate on user-supplied information to construct an XPath query for XML data. An attacker can gain detailed information on how the XML data is structured or access data that is not normally accessible by sending malicious information to the website.
These vulnerabilities can also elevate the attacker’s privileges in the application if the XML data is being used for authentication.
You can avoid XPath injection by similar techniques used to prevent SQL injection:
- Sanitize all user input.
- When sanitizing, verify the data type, format, length, and content.
- In client-server applications, perform validation at both the client and the server sides.
- Thoroughly test applications especially user input.
Cross-Site Scripting (XSS) attacks happen when an attacker uses a web application to send malicious code (usually a browser-side script) to other users. Vulnerabilities that allow these attacks can occur anywhere a web application receives input from a user, within the output it generates, without validating or encoding it.
In summation, there are some key points to bear in mind in writing secure Java code. You should always think about security in the development of your application in the design stage and code reviews, as well as look for vulnerabilities in your Java code and take advantage of the Java security APIs and libraries.
Only ever use highly rated vendor tools to monitor and log your code for security issues. This means you should investigate the full list of application attack types and follow the recommended prevention methods.
If you use these guidelines for writing secure Java code applications in your organization, you can protect yourself and your applications against malicious attacks and data theft.