Welcome back! In this lesson, we will explore the concept of XSS injection, a critical security vulnerability in web applications. Understanding this topic is essential for building secure applications and protecting user data. XSS injection occurs when attackers exploit improperly handled inputs to inject malicious scripts into web pages.
This vulnerability affects Java web applications with REST APIs that serve content to frontend applications. When user-supplied data is stored and retrieved without proper sanitization, attackers can inject scripts that execute in victims' browsers, leading to session hijacking, data theft, and unauthorized actions.
This lesson will guide you through the process of identifying, exploiting, and mitigating XSS injection vulnerabilities using server-side sanitization in a Java Spring Boot REST API. Let's dive in! 🚀
XSS injection is a technique used by attackers to exploit vulnerabilities in web applications. When user inputs are not properly validated or sanitized, attackers can inject malicious scripts that execute in other users' browsers. This can lead to unauthorized access, data breaches, and even session hijacking.
In our pastebin application, we have a snippet preview feature that displays user-submitted code. This feature stores and retrieves HTML content through a REST API. While client-side protection with libraries like DOMPurify (which we'll cover later in this lesson) is important, we also need server-side sanitization to prevent malicious content from being stored in the database in the first place.
Why? Because:
- Attackers might bypass the frontend and send requests directly to your API
- Other clients or integrations might not implement proper sanitization
- Defense in depth: multiple layers of security are always better
Now, let's look at how this vulnerability manifests in our Java REST API.
Our example focuses on a Spring Boot REST API that stores and retrieves code snippets. Here's the vulnerable version of our SnippetController:
Vulnerable Spring REST Controller:
This controller is vulnerable because it stores user-supplied content directly into the database without any sanitization. Even if your React frontend uses DOMPurify, attackers can bypass it by sending direct API requests.
The vulnerability becomes particularly dangerous because the injected code will execute for anyone who views the snippet. Here are two examples of how an attacker might exploit this vulnerability by directly calling your API:
Example 1 - Simple Alert (Educational Purpose):
This payload creates an img tag that intentionally fails to load, triggering the onerror event. When triggered, it shows an alert() containing the user's cookies.
Example 2 - Data Theft (Real Attack Scenario):
This more sophisticated attack appears harmless with a "Loading..." message but secretly sends the viewer's cookies to the attacker's server. If an administrator views this snippet, their privileged session could be hijacked.
Now that we understand the severity of these vulnerabilities, let's look at how we can protect against them using server-side sanitization...
The first line of defense is server-side sanitization - cleaning user input before it ever reaches your database. The OWASP Java HTML Sanitizer is a powerful library specifically designed for this purpose in Java applications.
First, ensure the dependency is in your pom.xml:
Now, let's implement server-side sanitization in our SnippetController:
While server-side sanitization is essential, you should also use client-side protection as an additional layer of defense. In your React application, use DOMPurify when rendering HTML content:
This creates a defense-in-depth strategy:
- Server-side: OWASP sanitizer prevents malicious content from being stored
- Client-side: DOMPurify provides an additional safety net when rendering
In this lesson, we explored XSS injection vulnerabilities in a Java Spring Boot REST API that serves a React frontend. We learned how attackers can bypass client-side protections by sending malicious content directly to your API, and how to implement a robust dual-layer defense using both server-side sanitization (OWASP Java HTML Sanitizer) and client-side sanitization (DOMPurify in React). This approach provides comprehensive protection against XSS attacks while still allowing legitimate HTML content when needed.
Key takeaways:
- Always implement server-side sanitization before storing user content in your database
- Use whitelist-based approaches that explicitly allow safe HTML tags and attributes
- Client-side protection (like DOMPurify) provides an additional safety layer
- Never trust client-side validation alone - always validate and sanitize on the server
- Test your sanitization policies thoroughly to ensure they block attacks while preserving legitimate content
As you move forward, practice these techniques in the exercises that follow to reinforce your understanding. Stay tuned for the next lesson, where we'll continue to build on these foundational security concepts. Keep up the great work! 🎉
