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
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.
Validating a RequestParam To do so, we'll use the @Min and @Max annotations: @GetMapping("/name-for-day") public String getNameOfDayByNumber(@RequestParam @Min(1) @Max(7) Integer dayOfWeek) { // ... } Any request that doesn't match these conditions will return an HTTP status 400 with a default error message.
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.
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
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());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With