Anti Cross-Site Scripting (XSS) For Java Web Application
In this tutorial, I am showing how to protect cross site scripting (xss) attacks for a java web application.
Cross-site scripting (XSS) happens, when an attacker injects malicious client sides scripts in the application.
How can we prevent Cross-site scripting (XSS)?
We can prevent xss attacks through hibernate validator’s @safehtml, which prevents HTML tags for XSS protection. @safehtml ensure that it contains no malicious code, such as embedded <script> elements.
pom.xmlYou need to have following pom.xml, hibernate validator’s internally using org.jsoup, We are using spring boot application in order to test the scenario.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-validating-form-input</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/javax.validation/validation-api --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.0.Final</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.2</version> </dependency> </dependencies> <repositories> <repository> <id>spring-releases</id> <name>Spring Releases</name> <url>https://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> <name>Spring Releases</name> <url>https://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project>
Application.java
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
StudentForm.java
package hello; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.SafeHtml; public class StudentForm { @NotNull @Size(min=2, max=50) @SafeHtml private String name; public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
WebController.java
package hello; import javax.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Controller public class WebController extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/results").setViewName("results"); } @GetMapping("/") public String showForm(StudentForm personForm) { return "form"; } @PostMapping("/") public String checkPersonInfo(@Valid StudentForm studentForm, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "form"; } return "redirect:/results"; } }
form.html
<html> <body> <form action="#" th:action="@{/}" th:object="${studentForm}" method="post"> <table> <tr> <td>Name:</td> <td><input type="text" th:field="*{name}" /></td> <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td> </tr> <tr> <td><button type="submit">Submit</button></td> </tr> </table> </form> </body> </html>
results.html
<html> <body> Congratulations! You are old enough to sign up for this site. </body> </html>
Project Structure
After deploying the application, if you enter any script to mock the xss attack, it will show as unsfe html content and reject it.
If you enter the
right values for the input it will shows below success messages.