【20200122】Spring Boot Security Best Practices - 图1

This month’s cheat sheet is about how you can secure your Spring Boot application. Spring Boot has dramatically simplified the development of Spring applications. Its autoconfiguration and starter dependencies reduce the amount of code and configuration you need to begin an app. If you were used to Spring and lots of XML in back in the day, Spring Boot is a breath of fresh air.
This is already our fourth cheat sheet this year, having posted Type Inference in Java, GitHub Security best practices, and Zip Slip in previous months. Look out for a Maven security cheat sheet coming soon!
This post was originally written in blog form and in more detail with Matt Raible, fellow Java Champion and Developer Advocate at Okta. We both work for companies in the security industry, love Java, and want to help developers create more secure applications, so what better to produce than a good looking cheat sheet on Spring Boot Security!
Without further ado, you should print out the cheat sheet and read up on some more detail about each of the tips below. Note that the original, more detailed post can be found on the Okta blog.

1. Use HTTPS in Production

TLS/SSL certificates used to be expensive, and HTTPS was considered slow. Machines have become much faster, solving the performance problem, and Let’s Encrypt provides free TLS certificates. These two developments have changed the game and caused TLS to become mainstream.
To force HTTPS in your Spring Boot app, you can extend WebSecurityConfigurerAdapter and require a secure connection.

  1. @Configuration
  2. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Override
  4. protected void configure(HttpSecurity http) throws Exception {
  5. http.requiresChannel().requiresSecure();
  6. }
  7. }

Cloud providers can greatly simplify TLS certificates. Amazon Certificate Manager is exactly like Let’s Encrypt except it’s built into all of the AWS products/services by default. It lets you provision 100% free SSL certs and handles automatic renewal, etc., with literally zero effort/config. Heroku has Automated Certificate Managementtoo.

2. Test Your Dependencies

There’s a good chance you don’t know how many direct dependencies your application uses. It’s extremely likely you don’t know how many transitive dependencies your application uses. This is often true, despite dependencies making up the majority of your overall application. Attackers target open source dependencies more and more, as their reuse provides many victims for a malicious hacker. It’s important to ensure there are no known vulnerabilities in the entire dependency tree of your application.
Snyk tests your application build artifacts, flagging those dependencies that have known vulnerabilities. It provides you with a list of vulnerabilities that exist in the packages you’re using in your application as a dashboard.
【20200122】Spring Boot Security Best Practices - 图2
Additionally, it will suggest upgrade versions or provide patches to remediate your security issues, via a pull request against your source code repository. Snyk also protects your environment, by ensuring that any future pull requests raised on your repository are automatically tested (via webhooks) to make sure they do not introduce new known vulnerabilities.
Snyk is available via a web UI as well as a CLI, so you can easily integrate it with your CI environment, and configure it to break your build when vulnerabilities exist with a severity beyond your set threshold.
You can use Snyk for free for open source projects or for private projects with a limited number of monthly tests.

3. Enable CSRF Protection

Cross-Site Request Forgery) is an attack that forces a user to execute unwanted actions in an application they’re currently logged into.
Spring Security has excellent CSRF support that’s on by default. If you’re using Spring MVC’s <form:form> tag or Thymeleaf and @EnableWebSecurity, the CSRF token will automatically be added as a hidden input field.
If you’re using a JavaScript framework like Angular or React, you will need to configure the CookieCsrfTokenRepository so JavaScript can read the cookie.

  1. @EnableWebSecurity
  2. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Override
  4. protected void configure(HttpSecurity http) throws Exception {
  5. http
  6. .csrf()
  7. .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
  8. }
  9. }

Spring Security automatically adds a secure flag to the XSRF-TOKEN cookie when the request happens over HTTPS. Spring Security doesn’t use the SameSite=strict flag for CSRF cookies, but it does when using Spring Session or WebFlux session handling.

4. Use a Content Security Policy to Prevent XSS Attacks

Content Security Policy (CSP) is an added layer of security that helps mitigate XSS (cross-site scripting)) and data injection attacks. To enable it, you need to configure your app to return a Content-Security-Policy header. You can also use a <meta http-equiv="Content-Security-Policy"> tag in your HTML page.
Spring security provides a number of security headers by default. Spring Security does not add a CSP by default. You can enable the CSP header in your Spring Boot app using the configuration below.

  1. @EnableWebSecurity
  2. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Override
  4. protected void configure(HttpSecurity http) throws Exception {
  5. http.headers()
  6. .contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/");
  7. }
  8. }

5. Use OpenID Connect for Authentication

OpenID Connect (OIDC) is an OAuth 2.0 extension that provides user information. It adds an ID token in addition to an access token, as well as a /userinfo endpoint that you can get additional information from. It also adds an endpoint discovery feature and dynamic client registration.
The diagram below shows how OIDC works for authentication.
【20200122】Spring Boot Security Best Practices - 图3

6. Use Password Hashing

Storing passwords in plain text is one of the worst things you can do for the security of your app. Luckily, Spring Security doesn’t allow plain text passwords by default. It also ships with a crypto module you can use for symmetric encryption, key generation, and password hashing (a.k.a., password encoding).
PasswordEncoder is the main interface for password hashing in Spring Security and looks as follows:

  1. public interface PasswordEncoder {
  2. String encode(String rawPassword);
  3. boolean matches(String rawPassword, String encodedPassword);
  4. }

Spring Security provides several implementations, the most popular being BCryptPasswordEncoder and Pbkdf2PasswordEncoder.

7. Use the Latest Releases

There are various reasons to regularly upgrade the dependencies in your application. Security is one of the most important reasons that will give you the motivation to upgrade. The start.spring.io starter page uses the most recent versions of Spring packages as well as dependencies, where possible.
Infrastructure upgrades are often less disruptive than dependency upgrades, as library authors vary in their sensitivity to backward compatibility and behaviour changes between releases. That being said, you have three options when you find a security vulnerability in your configuration: Upgrade, Patch or Ignore. Upgrades are the safest, in terms of the overall health of your application, but often they’re not always an option. When this is the case, patches can eliminate vulnerabilities from your package, which you can often get from a security specialist, like Snyk. Ignoring a vulnerability is, of course, an option, but not a good one. Perhaps you know of a vulnerability, but do not believe it is directly exploitable. Keep in mind that it might not be in your application flow today, but at some point, a developer might add additional code that uses a vulnerable path.

8. Store Secrets Securely

Sensitive information such as passwords, access tokens, etc., should be handled with care. You cannot leave these around, pass them in plain text, or be predictable if keeping them in your local storage. As (GitHub) history has proved time and time again, developers do not think carefully enough about how they store their secrets.
A good practice is to store secrets in a vault that can be used to store, provide access to, and even generate credentials to services that your application may use. Vault by HashiCorp makes storing secrets trivial, as well as offering a number of additional services. You can also integrate with common authentication mechanisms such as LDAP to obtain tokens.
If this interests you, be sure to invest some time looking at the Spring Vault which adds an abstraction over the HashiCorp Vault, providing Spring annotation based access for clients, allowing them to access, store and revoke secrets without getting lost in the infrastructure. The following code snippet shows how easy it is to extract a password from the Spring Vault using an annotation.

  1. @Value("${password}")
  2. String password;

9. Pen Test Your App

The OWASP ZAP security tool is a proxy that performs penetration testing against your live application at runtime. It’s a popular (over 4k stars) free, open source project that is hosted on GitHub.
Two approaches OWASP ZAP uses to find vulnerabilities are Spider and Active Scan. The Spider tool starts with a seed of URLs, which it will access and parse through each response, identifying hyperlinks and adding them to a list. It will then access these newly found URLs and recursively continue, creating a map of URLs for your web application. The Active Scan tool will automatically test your selected targets against a list of potential vulnerabilities. It provides you with a report that shows where your web application is exploitable, with details about the vulnerability.

10. Have Your Security Team do a Code Review

Code reviews are essential for any high performing software development team. At Okta, all the production code and official open source projects are required to go through an analysis from our expert security team. You might not have security experts at your company, but if you’re dealing with sensitive data, maybe you should