'How to validate and sanitize HTTP Get with Spring Boot?

I keep getting this annoying error from Checkmarx code scanner,

Method getTotalValue at line 220 of src\java\com\example\PeopleController.java 
gets user input for the personName element. This element’s value then flows through
the code without being properly sanitized or validated and is eventually 
displayed to the user. This may enable a Cross-Site-Scripting attack. 

Here is my code. I think I did ALL the validation necessary. What else???

@Slf4j
@Configuration
@RestController
@Validated 

public class PeopleController {

    @Autowired
    private PeopleRepository peopleRepository; 

    @RequestMapping(value = "/api/getTotalValue/{personName}", method = RequestMethod.GET)
    @ResponseBody
    public Integer getTotalValue(@Size(max = 20, min = 1, message = "person is not found") 
    @PathVariable(value="personName", required=true) String personName) {

        PersonObject po = peopleRepository.findByPersonName(
                            Jsoup.clean(personName, Whitelist.basic()));

        try {
            return po.getTotalValue(); 
            } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }  


@ExceptionHandler
    public String constraintViolationHandler(ConstraintViolationException ex) {
        return ex.getConstraintViolations().iterator().next()
                .getMessage();
    } 

} 

There must be some missing validation. How to validate HTTP GET properly with Spring Boot



Solution 1:[1]

You need to be a bit careful with these scanning tools as sometimes these tools do report false positives and sometimes no code changes are required. I am no expert of checkmarx but be sure that this tool really understands bean validation annotations that you are using & the call Jsoup.clean(personName, Whitelist.basic()) .

I think I did ALL the validation necessary. What else???

First you need to understand the different between application level input sanitation & business level input validation for a controller. What you are doing here is second part & first might be missing in your set up which is exclusively done from security perspective & usually set up for whole application.

You are using @Size annotation to limit an input's size but that doesn't guarantee about bad strings - strings that can cause XSS attacks. Then, you are using call Jsoup.clean(personName, Whitelist.basic())) to clean this size validated input. As I am not sure what that call does so you need to ensure that new value is XSS - Safe. You are immediately passing that value to DB call & then returning an Integer to caller/client so I am very pessimist about any possibility of an XSS attack here but tool is saying so.

There must be some missing validation. How to validate HTTP GET properly with Spring Boot

As I explained earlier, input validation is a term usually meant for business logic level input validation while input sanitization / clean up is about security. In Spring Boot environment, this is usually done by using Spring Security APIs & enabling XSS filters or by writing your own XSS filter and plug it in your application. Filter comes first and your controller later so your controller will always have a sanitized value & you will apply business validations on that sanitized value.

This is a broad level answer & for code etc you might do google. Also suggest to read more about XSS attacks. Just understand that there are multiple ways to accomplish same goal.

3 Ways to Prevent XSS

XSS prevention in Java

How to create filter in Spring RESTful for Prevent XSS?

Cross Site Scripting (XSS) Attack Tutorial with Examples, Types & Prevention

In last link, its mentioned ,

The first step in the prevention of this attack is Input validation. Everything, that is entered by the user should be precisely validated, because the user’s input may find its way to the output.

& that you are not doing in your code so I would guess that there is no XSS.

EDIT:

There are two aspects of XSS security - first not allowing malicious input to server side code & that would be done by having an XSS filter & Sometimes, there is no harm in allowing malicious input ( lets say you are saving that malicious input to DB or returning in API response ) .

Second aspect is instructing HTML clients about possible XSS attacks ( if we know for sure that API client is going to be HTML / UI ) then we need to add X-XSS-Protection header & that would be done by below code. This will enable browser to turn on its XSS protection feature ( if present ) .

@Override protected void configure(HttpSecurity http) throws Exception {

http.headers().xssProtection()....

}

What is the http-header “X-XSS-Protection”?

Is Xss protection in Spring security enabled by default?

For first aspect i.e. writing filter - refer my this answer and links in that answer.

I think, I have wrongly written above that Spring Security provides input sanitation filters , I guess , it doesn't. Will verify and let you know. I have written my custom filter on the lines mentioned in answer to this question - Prevent XSS in Spring MVC controller

You have to also understand that Spring Boot gets used to write traditional MVC apps too where server side presents HTML to render too . In case of JSON responses ( REST APIs ) , UI client can control what to escape and what not, complexity arises because JSON output is not always fed to HTML clients aka browsers.

Solution 2:[2]

I have an excellent (IMHO) solution with Jsoup and Apache Commons. I Hope it will help other people

Add this class

import org.apache.commons.lang.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;

public class SecurityEscape {

    public static String cleanIt(String arg0) {
        return Jsoup.clean(
                StringEscapeUtils.escapeHtml(StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeSql(arg0)))
                , Whitelist.basic());
    }


} 

Now you can clean all incoming strings from GET or POST like this in your controller

    @PostMapping("/api/blah") or GET whatever . .. . .  .
    public ResponseEntity<?> testIt(String whatever) { 

String whatever = SecurityEscape.cleanIt(whatever); 

... .. 

AFTER THIS CHECKMARX SAYS THIS IS A SAFE CODE

Special thanks to @Sabir Khan for guidance

Solution 3:[3]

This worked for me ----

import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.util.StringUtils;

public class SecurityUtil {

    private SecurityUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     *  Remove escape characters like Html/Js scripts from input if present
     * @param str Input string
     * @return sanitize string
     */
    public static String cleanIt(String str) {
        return Jsoup.clean(
                StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript (StringUtils.replace(str, "'", "''")))
                , Whitelist.basic());
    }
}

Solution 4:[4]

This was what also worked for me with Checkmarx v8.8.0

offendingValue = StringEscapeUtils.escapeHtml(offendingValue);

btw, I tried the solution at: https://github.com/mehditahmasebi/spring/blob/master/spring-xss-filter/src/main/java/com/spring/boot/web/WebConfig.java withour success

Solution 5:[5]

org.apache.commons.lang3.StringEscapeUtils is deprecated for org.apache.commons.text.StringEscapeUtils (documentation)

Do not forget to import it in your dependencies (example).

The use is the same, eg:

import org.apache.commons.text.StringEscapeUtils;

...

String escapedHtml = StringEscapeUtils.escapeHtml4("Hello world!");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 john
Solution 3 StackOverFlow
Solution 4 Joel Mata
Solution 5