Automating security tests — how?
Hello everyone! 👋🏼
In our previous article on security testing, we discussed how we can combine skills to write better tests. While we cannot automate all activities in security testing, most of the security test cases that provide deterministic outcomes can be automated. Today, we’ll dive deeper into writing automated tests to verify the security aspects of an application feature (i.e. file upload) and explore writing automated tests on the unit-level and API-level to verify the security aspects of the file upload functionality.
We will use the below automation tools:
Before we start writing any tests, let’s understand the file upload feature, identify the potential security loopholes, and then draft the test cases that can be automated.
File upload feature
Assume the application under test has a simple form submission that allows users to upload a file with the following restrictions:
- File types allowed: PDF, JPEG/JPG
- File size should not exceed 1 MB
A rough model diagram of the file upload feature is as follows:
When an authorised user uploads a file on the frontend, the attachment is converted into a base64 string and passed to the backend through the /api/upload API along with file content-type and filename (w/ extension) in the request body. On success, the file would be processed further in the backend.
From requirement study, we can filter down to the following security tests to automate:
Writing the unit tests
The unit tests on the frontend will mostly test the functional aspects of the file upload feature, therefore we will look at the backend unit tests that should focus mainly on the security aspect of the feature. Apart from verifying the file size, the backend codes should also check the legitimacy of the incoming file by checking the file’s magic bytes.
Magic bytes/numbers are hex file signatures of few bytes in length, present at the leading or trailing positions of the file’s binary. It is primarily used to identify the file type.
Unit tests to verify the file’s authenticity:
Running the command `jest` will run the unit test and generate the following output:
In the above tests, we are verifying the base64 string along with the file’s content-type. With the unit tests, we are ensuring that the below requirements are satisfied:
- A valid JPEG/JPG file is accepted
- A JPEG/JPG file with invalid leading or trailing file signatures are rejected
- An incorrect JPEG/JPG file data is rejected
Likewise, we should also add appropriate unit tests for verifying the magic bytes of PDF files.
Writing the API tests
To allow for better security, the file validation logic is implemented in the application backend. When a user uploads a file, the file data is passed to the backend through an API call. On the API level, we need to ensure at least 2 aspects: authentication and data validation.
File upload is a sensitive feature that any malicious actor could exploit by uploading malicious files to pollute/breach the application and its systems. It is highly recommended to allow only authorised users to access this module by verifying their identity through authentication features like secure login.
In our case, let us assume that we have a login mechanism to handle a user session. When the user uploads a file, the file upload API call should include the generated session token in the API header to allow the backend to identify and authenticate the request.
The API tests for authentication are as follows:
In the file upload API, the request data should include the file data (in base64 string format), along with additional attributes. All attribute values should be scoped, strictly-typed and verified. The API tests to perform request data validation would include:
By adding security tests on different test levels, we are verifying that all layers of the application feature have the correct configuration, restrictions, and expected behaviour.
If you like to access the above tests in full, you can click on our GitHub link.
While this article does not provide a comprehensive list of security test cases to automate, we hope that it has left you with an idea of the different types of tests that we could write to verify not only the functional portions, but also the security portions of a feature or an application.
- Merlin 💛