130n@calvinlai.com
  • About Calvin Lai (fkclai)
  • My Work
  • Cyber Security
    • Cyber Security Centre (CSC)
      • Why we need a CSC
      • CSC Team Structure: Roles, Functions, and Tools
        • Key Function & Role
        • Tools & Platforms
        • People
        • Outsource Strategy
      • HRMC Executive Paper
  • Detection and Response
    • Playbook: Threat Prioritization & Automated Response Strategies
      • Scenario: Detecting and Mitigating a Ransomware Attack
      • Scenario: DC Sync Attack Detected and Mitigated
      • Scenario: Pass-the-Hash (PtH) Attack Detected and Contained
      • Scenario: Phishing Campaign with Malware / Credential Theft Detected and Mitigated
  • Application Architecture
    • Comparison of MVC , N-tier and Microservice Architecture
  • Application Security
    • OAuth, SAML, and OpenID Connect: Key Differences and Use Cases
    • Secure Coding Principles
    • HTTP Header Security Principles
    • Mitigating Broken Object Level Authorization (BOLA)
    • Spring Boot Validation
    • Output Encoding in JavaServer Faces (JSF)
    • Session Management Security Issues
    • Common API Security Problems
      • Broken Authentication
      • Excessive Data Exposure
      • Lack of Resources & Rate Limiting
      • Broken Function Level Authorization
      • Unsafe Consumption of APIs
    • JAVA Exception Handling
    • File Upload Validation
    • OAuth 2.0 Security
      • Insecure Storage of Access Tokens
    • Microservice Security
      • Sample Coding Demo
        • Service Implementation
        • Client Interaction
      • Security Solution for Microservices Architecture
    • Modifying and Protecting Java Class Files
      • Modify a Class File Inside a WAR File
      • Direct Bytecode Editing
        • Steps to Directly Edit a Java Class File
          • Update: Java Bytecode Editing Tools
      • Techniques to Protect Java Class Files
        • Runtime Decryption in WebLogic
    • JAVA Program
      • Secure, Concurrent Web Access Using Java and Tor
      • Creating a Maven Java project in Visual Studio Code
  • Exploit/CVE PoC
    • ZeroLogon Exploit
    • Remote Retrieved Chrome saved Encrypted Password
    • Twitter Control an RCE attack
  • Hacking Report (HTB)
    • Hits & Summary
      • Tools & Cheat Sheet
    • Windows Machine
      • Love 10.10.10.239
      • Blackfield 10.10.10.192
      • Remote 10.10.10.180
      • Sauna 10.10.10.175
      • Forest 10.10.10.161
      • Sniper
      • Json
      • Heist
      • Blue
      • Legacy
      • Resolute
      • Cascade
    • Linux Machine
      • Photobomb 10.10.11.182
      • Pandora 10.10.11.136
      • BountyHunter 10.10.11.100
      • CAP 10.10.10.245
      • Spectra 10.10.10.229
      • Ready 10.10.10.220
      • Doctor 10.10.10.209
      • Bucket 10.10.10.212
      • Blunder 10.10.10.191
      • Registry 10.10.10.159
      • Magic
      • Tabby
  • Penetration Testing
    • Web Application PenTest
    • Network/System PenTest
    • Mobile Penetration Test
      • Certificate Pinning
        • Certificate Pinning Bypass (Android)
          • Root a Android Device
          • Setup Proxy Tool - Burp Suite
      • Checklist
  • Threat Intelligence
    • Advanced Persistent Threat (APT) groups
      • North Korean APT Groups
      • Chinese APT Groups
      • Russian APT Groups
      • Other APT
  • Red Team (Windows)
    • 01 Reconnaissance
    • 02 Privileges Escalation
    • 03 Lateral Movement
    • 04 AD Attacks
      • DCSync
    • 05 Bypass-Evasion
    • 06 Kerberos Attack
    • 99 Basic Command
  • Exploitation Guide
    • 01 Reconnaissance
    • 02 Port Enumeration
    • 03 Web Enumeration
    • 04 Windows Enum & Exploit
      • Windows Credential Dumping
        • Credential Dumping: SAM
        • Credential Dumping: DCSync
      • Kerberos Attack
      • RDP
    • 05 File Enumeration
    • 06 Reverse Shell Cheat Sheet
      • Windows Reverse Shell
      • Linux Reverse Shell
    • 07 SQL Injection
    • 08 BruteForce
    • 09 XSS Bypass Checklist
    • 10 Spring Boot
    • 11 WPA
    • 12 Payload list
  • Vuln Hub (Writeup)
    • MrRobot
    • CYBERRY
    • MATRIX 1
    • Node-1
    • DPwwn-1
    • DC7
    • AiWeb-2
    • AiWeb-1
    • BrainPan
  • CTF (Writeup & Tips)
    • CTF Tools & Tips
    • Hacker One
    • CTF Learn
    • P.W.N. University - CTF 2018
    • HITCON
    • Pwnable
      • 01 Start
  • Useful Command/Tools
    • Kali
    • Windows
    • Linux
  • Offensive Security Lab & Exam
    • Lab
    • Tools for an Offensive Certification
      • Strategy for an Offensive Exam Certification
        • CVEs
        • Privilege Escalation
        • Commands
        • Impacket
  • ISO 27001
    • Disclaimer
    • What is ISO 27001
      • Implementation
    • Documentation
    • Common Mistake
    • Q&A
      • Can internal audit to replace the risk assessment
      • Is it sufficient for only the IT department head to support the ISO 27001 program
      • Does the Business Continuity Plan (BCP) and a Disaster Recovery Plan (DRP) are the same?
    • ISO 27001 Controls and Domains
      • 1. Information Security Policies
      • 2. Organization of Information Security
      • 3. Human Resource Security
      • 4. Asset Management
      • 5. Access Control
      • 6. Cryptographic Controls
      • 7. Physical and Environmental Security
      • 8: Operational Security
      • 9. Communications Security
      • 10. System Acquisition, Development, and Maintenance
      • 11. Supplier Relationships
      • 12: Information Security Incident Management
      • 13. Information Security Aspects of Business Continuity Management
      • 14. Compliance
Powered by GitBook
On this page
  • Step-by-Step Implementation
  • 1. Add Dependencies
  • 2. Define the Model
  • 3. Create the Controller
  • 4. Global Exception Handling
  • 5. Centralized Validation Messages
  • 6. Client-Side Validation
  • 7. Test Validation Logic
  • Execution Flow
  • Key Points for Developers
  • Summary and Key Takeaways
  • Reference Links

Was this helpful?

  1. Application Security

Spring Boot Validation

Spring Boot Validation to Address Lack of Input Validation

Lack of Input Validation is a common security vulnerability where input data is not properly validated before processing, which can lead to various attacks, including SQL injection, cross-site scripting (XSS), and buffer overflow. Spring Boot provides robust mechanisms to enforce input validation, ensuring that only valid data is processed.

Maps to OWASP Top 10

This vulnerability is categorized under A04:2021 - Insecure Design in the OWASP Top 10, emphasizing the need for secure design principles, including input validation.

Step-by-Step Implementation

1. Add Dependencies

First, add the necessary dependencies to your pom.xml file to enable validation. Ensure you have the following dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. Define the Model

Create a model class with validation annotations to enforce input constraints. Use Hibernate Validator, which is the reference implementation of the Bean Validation specification.

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

public class User {

    @NotBlank(message = "Name is mandatory")
    @Size(min = 2, max = 30, message = "Name must be between 2 and 30 characters")
    private String name;

    @Email(message = "Email should be valid")
    @NotBlank(message = "Email is mandatory")
    private String email;

    @NotBlank(message = "Password is mandatory")
    @Size(min = 6, message = "Password must be at least 6 characters")
    private String password;

    // Getters and Setters
}

3. Create the Controller

In the controller, use @Valid annotation to trigger validation and BindingResult to handle validation errors.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<?> createUser(@Valid @RequestBody User user, BindingResult result) {
        if (result.hasErrors()) {
            Map<String, String> errors = new HashMap<>();
            result.getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));
            return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
        }

        // Process user
        // start the business logic of this API service
        return new ResponseEntity<>("User created successfully", HttpStatus.OK);
    }
}

4. Global Exception Handling

Implement a global exception handler to manage validation errors consistently across the application.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach(error -> {
            // implement the bilangual logic here
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}

5. Centralized Validation Messages

Store validation messages in a properties file to maintain consistency and facilitate localization. This also makes it easier to update error messages without changing the code.

# messages.properties
NotBlank.user.name=Name is mandatory
Size.user.name=Name must be between 2 and 30 characters
Email.user.email=Email should be valid
NotBlank.user.email=Email is mandatory
NotBlank.user.password=Password is mandatory
Size.user.password=Password must be at least 6 characters

6. Client-Side Validation

Implement client-side validation in addition to server-side validation. This provides immediate feedback to users and reduces unnecessary requests to the server. However, always remember that client-side validation is not a substitute for server-side validation.

7. Test Validation Logic

Write unit and integration tests to verify that your validation logic works as expected. Use testing frameworks like JUnit and Mockito to create test cases for various input scenarios.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.databind.ObjectMapper;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
public class UserControllerTest {

    @Autowired
    private WebApplicationContext context;

    @MockBean
    private UserService userService;

    private MockMvc mockMvc;

    @Test
    public void testCreateUserInvalidInput() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
        User user = new User();
        user.setName(""); // Invalid name
        user.setEmail("invalid-email"); // Invalid email

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(new ObjectMapper().writeValueAsString(user)))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.name").value("Name is mandatory"))
                .andExpect(jsonPath("$.email").value("Email should be valid"));
    }
}

Execution Flow

  1. Client Request: A client sends a POST request to /api/users with user details in the request body.

  2. Request Mapping: The createUser method in UserController handles the request. The @Valid annotation triggers the validation process on the User object.

  3. Validation Process: Hibernate Validator checks the constraints defined in the User model:

    • @NotBlank ensures that fields are not null or empty.

    • @Size checks the length of the input strings.

    • @Email verifies that the email format is valid.

  4. Binding Result: If validation fails, BindingResult captures the validation errors.

  5. Error Handling: The controller checks if there are validation errors. If there are, it collects the error messages and returns a BAD_REQUEST response with the error details.

  6. Success Handling: If validation passes, the controller proceeds to process the user data and returns an OK response with a success message.

Key Points for Developers

  • Use Validation Annotations: Leverage annotations like @NotBlank, @Size, and @Email to enforce input constraints at the model level.

  • Handle Validation Errors: Use BindingResult to capture and handle validation errors gracefully.

  • Return Meaningful Responses: Provide clear and informative error messages to the client when validation fails.

  • Test Validation Logic: Regularly test your validation logic to ensure it correctly handles various input scenarios.

  • Performance Considerations: While validation is crucial, be mindful of its impact on performance. Use validation judiciously, especially for fields that are not frequently validated or have complex validation rules.

Summary and Key Takeaways

Implementing input validation in Spring Boot helps prevent common security vulnerabilities related to invalid input data. By using validation annotations, handling errors gracefully, and providing meaningful responses, developers can ensure that only valid data is processed by the application.

Reference Links

PreviousMitigating Broken Object Level Authorization (BOLA)NextOutput Encoding in JavaServer Faces (JSF)

Last updated 6 months ago

Was this helpful?

Spring Boot Validation Documentation:

Hibernate Validator Documentation:

OWASP Input Validation Cheat Sheet:

Spring Boot Validation
Hibernate Validator
OWASP Input Validation Cheat Sheet