Solving Java security issues in my Spring MVC application
2021年3月15日
0 分で読めますThe Spring MVC framework is a well-known Java framework to build interactive web applications. It implements the Model-View-Controller architecture pattern to separate the different aspects of your application. Separating the different logic elements like representation logic, input logic, and business logic is generally considered good architectural practice. This separation of concerns, when implemented correctly, provides you, for instance, less code duplication and multiple views for the same model.
Spring MVC is part of the Spring framework and focuses on building Java web applications. This can either be a standalone application using a separate web server like tomcat or Spring- boot application.
For this article, I created a Spring MVC application with JSP (Java Server Pages) web pages that runs on a tomcat server. The code I create is very basic and straightforward. Although the code works perfectly, I did make some security-related mistakes. Let’s see how we can detect these mistakes in my Spring MVC application performing Java static code analyses and how to fix them.
My Spring MVC Java Application
The Spring MVC Java application I created is very straightforward. It is a Java 11 based application using a very recent version of spring-web-mvc
. The implementation respects the model-view-control pattern and interacts with the user via simple JSP pages. You can find this example application on GitHub and you can run it using the mvn tomcat7:run
.
The basic features of the application are:
Upload a file to a folder
Upload and unzip a file
Listing uploaded files
Write a message on the message board
List all the messages
Search for a specific message.
I limited the dependencies to the bare minimum. Although I could use some well-known libraries to do the heavy lifting, I wrote all the business logic myself. In addition to springweb-mvc I rely on:
commons-fileupload
for uploading the filesjstl
for logic in my JSP filesh2
in-memory database for the messages.
I know that this application contains some security code mistakes. Let’s take the brand new Snyk Code for a spin and see how effective the Java static code analysis is in finding these code vulnerabilities I created.
Snyk Code - Java Static Code Analysis Tool
Snyk Code is a new Snyk product that focuses on finding vulnerable code constructions in multiple languages, including Java. The Java code analysis for Snyk Code also supports the major frameworks like Spring MVC that I am currently using. Snyk Code is a Static Application Security Testing (SAST) tool. Although SAST is very much a term only used in the InfoSec world, it does precisely what it says. It statically analyses your Java code and looks for possible security vulnerabilities. Snyk Code leverages machine learning to provide a super-fast developer-friendly way to find vulnerabilities in your code. For this blog post, we will use the GitHub integration with Snyk to leverage Snyk Code.
Note: I am currently using an early launch of Snyk Code. It will most likely be generally available in April.
Scanning my Java Spring MVC application with Snyk code
I activated Snyk Code in the settings on my Snyk account. Once the activation is completed, be aware that every repository you import from now on, is scanned by Snyk Code. This also means that I permit that Snyk can actively inspect my code. We don’t need this when only using Snyk Open Sourceand scan for vulnerable dependencies. There we only need to read the manifest file like your pom.xml
or build.gradle
file.
After importing the GitHub repository containing my Spring MVC Java application, I almost immediately see that Snyk Code worked, and the Java code analysis found security issues.
It found a couple of path traversal issues related to the file upload logic. Snyk Code also detected multiple SQL Injection vulnerabilities, a couple of problems with cookies, and found hardcoded credentials. Let’s take a quick look at a couple of them.
Path traversal vulnerability in File upload
When uploading a file in my Spring MVC application, Snyk Code found out that I don’t do any sanitization on the incoming file. By blindly writing the file to the filesystem without checking it, path traversal is possible. When an attacker can craft a POST request where the filename looks evaluates to ../../../../../dir/file.x
, then we break out of the initial scope and write the file outside of the application. This also means an attacker might override an existing file.
Zip-slip path traversal vulnerability
A similar path traversal problem is found when uploading and unpacking Zip files in my Spring MVC application. I am creating the files on the filesystem by using the filenames in the zip file without sanitizing them. If your zip file looks like the one below, you will create or override files outside of the application’s scope.
1-rw-r--r-- 18-Apr-15 23:04 good.txt
2-rwxrwxrwx 18-Jun-03 17:06 ../../../../../../../../../../../../dir/file.x
This specific path traversal within a zip file is called a zip-slip vulnerability. In the past, many zip and unzip libraries contained such a security vulnerability. So remember to scan your dependencies with Snyk Open Source to catch these vulnerable libraries.
SQL Injection vulnerability when searching for messages
In the message repository I wrote for this Spring MVC application in Java, I manually create the search query using the given parameter. As you can see in the screenshot below, I do not use query parameterization. With query parameterization, you separate the parameters from the actual query string. You can validate and sanitize the parameters by binding them, for instance, to a specific type. Currently, I just concatenate the parameter to the existing query literal and execute. This means that I can hijack the SQL query.
Try the following search parameter '; UPDATE message SET text = 'EVIL
. I am breaking out of the original query and launching a new statement that updates all of the messages. This is probably not what you want, and luckily Snyk Code helped us find the vulnerability.
Other vulnerabilities found by the Java code analysis
Snyk also found some other issues that might cause danger. For instance, my database’s connection properties, including the username and password, are hardcoded in my repository. Snyk Code advised me not to do this, and that is valid.
Snyk Code also found an issue with a cookie I am setting. As this is a Spring MVC web application, I put a convenience cookie on the client system to store the userID. Nevertheless, the maximum age for this cookie is set to a year. If you store sensitive information in a cookie, it is unwise to set the maxAge to a high value. When you use cookies to store data temporarily, the cookie should be valid for a limited time. Snyk Code points me at this for a good reason
Conclusion
When creating a very straightforward web application in Java with Spring MVC a lot can happen. Note that I did not discuss all the issues Snyk Code found in this demo application. I leave this as an exercise for you.
If you create all the business logic yourself, security issues might slip in. Know that there are well-maintained libraries available that help you achieve the same goal. A great example within the spring framework are the spring-data libraries that can help you query your database. When you use external libraries, be aware of scanning them with Snyk Open Source to prevent including a vulnerable library. Nevertheless, including possible security issues in your own Java code happens quickly and can occur to anyone. Spotting these vulnerabilities in a code review session is hard. Luckily we have a great Java static code analysis tool like Snyk Code that helps you with this.