There is no doubt that Java runs a good portion of software and applications. According to Statista, Java is used by 40.2% of developers worldwide as of 2020. Java is the backbone of Android development, along with many enterprise-level applications and backend implementations.
java.security is a package that provides all the related security-based classes, interfaces, and enums for your Java-based applications. In this piece, we will go over different ways of implementing security techniques to increase your software’s hardness and reduce potential and common vulnerabilities that your application may face.
Dealing with Java Access Control
Access control is a process of protecting sensitive resources from unwanted access. When in development mode, it’s easy to just open up all the permissions to make coding faster. However, when we do this, we’re not developing our apps with a security-first approach. When security becomes a last port of thought, it usually also ends up being forgotten or implemented last minute — if not at all.
To ensure that your Java application is secure from the get-go, it is good practice to implement access control right from the beginning. To do this, you can use the Policy and Permission classes through the SecurityManager class.
SecurityManager is part of the java.lang package and is responsible for enforcing access control checks. When a class loader loads a class in the runtime, the Permission object automatically grants default permissions to it. During runtime, SecurityManager verifies the requested Permission granted against the installed Policy.
Here is an example of how to restrict access to a resource file in Java through SecurityManager:
What’s happening here is that SecurityManager validates the read request on the file, which is wrapped inside FilePermission.SecurityManager then delegates the request to AccessController, where it checks it against the installed Policy to decide accessibility.
Here is an example of what an example policy looks like:
Plain text passwords are the industry standard for compromised security. Over the past decade, we all know that passwords should never be stored in plain text. The best thing to do is to encrypt it. But how exactly do you do that in Java?
Java comes with multiple methods that allows you to scramble passwords in a repeatable way, also known as a cryptographic hash function. Here is an example of how to implement it in Java code:
There are multiple standards for hashing passwords. MD5 and SHA-521 are not recommended, mostly due to their age and ease of brute force cracking due to increased computing power over the years. The industry-recommended algorithms for cryptography are PBKDF2, BCrypt, and SCrypt. This is because these cryptographic algorithms allow for variable-length salts. The longer the salts, the stronger the overall strength of the hashed password.
Here is an example of setting up PBKDF2 in Java:
SSL Support in Java
SSL support is inbuilt with Java through certificates to establish a secure connection. To implement this in Java, you need two things: a valid certificate and the ability to verify the certificate.
Here is an example code snippet of how to store a valid certificate in the key-store file where public keys are generally placed.
To verify a certificate, we need to load the trust store where we placed all the trusted certificates. Here is how you do it in Java code:
And that’s basically it.
Working With Application Authentication
Authentication is the process of identifying a user and their rights to access certain information. To do this, additional data such as passwords, tokens, and other variety of authentication methodologies are employed.
Java comes with some default login modules — the Krb5LoginModule for Kerberos-based authentication, JndiLoginModule for username and password-based authentication backed by LDAP store, and KeyStoreLoginModule for cryptography key-based authentication.
Here is an example of how to set up a username and password in Java code through JndiLoginModule. The implementation gets the username and password from the user and verifies it against a directory service configured in JNDI:
The above is an example of an instance of the LoginContext to perform the login. Here is an example of a login configuration:
Supporting Secure Java Communication
Secure communication implementation is one of the key pillars to reducing network vulnerability. Without encryption layers, malicious users can read data packets as they are being transferred. SSL/TLS is an expected industry standard that provides encryption on network communication based on public keys. The Java Secure Socket Extension, also known as JSSE, provides SSL (version 3.0), TLS (version 1.0, 1.1. and 1.2), and DTLS (version 1.0 and 1.2) protocols for data encryption, server authentication, and optional client authentication. Using JSSE, security over data movements can be implemented on the server running any application protocol such as HTTP, Telnet, or FTP over TCP/IP. In Java, SSL/TLS support is accessible through SSLSocket as defined in the package java.security.ssl.
In addition to this, Java also supports SASL — that is, Simple Authentication and Security Layer — for standard authentication between the client and server. This is accessible through java.security.sasl. For GGS-API/Kerberos support — or Generic Security Service API — look at the package java.security.jgss.
Here is a quick sample code snippet on how to implement SSL communication in Java. In the sample code below, we are opening a secure connection using Java SSLSocket by using a SSLSocketFactory.
Conclusion: Spring Security
In short, when it comes to security, Java provides a good range of tools out of the box. While the above Java code snippets are useful as starting points, they are still quite low-level examples that need to be further integrated into your application. Java Spring is often used as a framework to extend Java’s core functionality in a structured manner, making it faster to develop applications and solutions for the business.
Java Spring has its own ways of implementing security, including authentication and authorization, and ways to protect against attacks like session fixation, clickjacking, and cross-site request forgery.
For example, when working with Java Spring security, you don’t need to fully implement the full OAuth RFC standard. The modules available reduces the workload and standardizes implementation for us. When it comes to Java, Java Spring is often synonymous with it. The good part about Java Spring and its security implementations is that anything coded inside a pure Spring application can also be used outside it, and vice versa.
The more security you have over your data, the more you reduce the surface area of your vulnerabilities. Ultimately, when it comes to security, the major point to keep in mind is encryption. It is one surefire way to ensure that your data is safe and secure, even in events of package hijacks and malicious tampering.