Proper input validation can prevent insertion of malicious data into the system. However, such validation fails to provide the assurance that validated data remains consistent throughout its lifetime. For instanceexample, if an insider is allowed to insert data into a database without validation, he she can glean unauthorized information or execute arbitrary code on the client side by means of attacks such as Cross Site Scripting (XSS) [OWASP 2011]. Output filtering to prevent such attacks is as important as input validation.
As with input validation, normalize data before filtering for malicious characters. To avoid vulnerabilities caused by data that bypasses validation, we recommend that all All output characters other than those known to be safe should be encoded to avoid vulnerabilities caused by data that bypasses validation.
Noncompliant Code Example
This noncompliant code example uses the MVC concept of the Java EE based Spring Framework to display some data to the user without encoding or escaping it.
Code Block | ||
---|---|---|
| ||
@RequestMapping("/getnotifications.htm") public ModelAndView getNotifications(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView(); trytry { UserInfo userDetails = getUserInfo(); List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); List<Notification> notificationList = notificationService.getNotificationsForUserId( userDetails.getPersonId()); for for(Notification notification: notificationList) { Map<String,Object>map = new HashMap<String,Object>(); map.put("id",notification.getId()); map.put( "message", notification.getMessage()); list.add( map); } mv.addObject("Notifications",list); } catch(Throwable t){ // log to file and handle } return mv; } |
Compliant Solution
...
Code Block | ||
---|---|---|
| ||
public class ValidateOutput {
// Allows only alphanumeric characters and spaces
private Pattern pattern = Pattern.compile("^[a-zA-Z0-9\\s]{0,20}$");
// Validates and encodes the input field based on a whitelist
private String validate(String name, String input) throws ValidationException {
String canonical = normalize(input);
if (!pattern.matcher(canonical).matches()) {
throw new ValidationException("Improper format in " + name + " field");
}
// Performs output encoding for non valid characters
canonical = HTMLEntityEncode(canonical);
return canonical;
}
// Normalizes to known instances
private String normalize(String input) {
String canonical = java.text.Normalizer.normalize(input, Normalizer.Form.NFKC);
return canonical;
}
// Encodes non valid data
public static String HTMLEntityEncode(String input) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (Character.isLetterOrDigit(ch) || Character.isWhitespace(ch)) {
sb.append(ch);
} else {
sb.append("&#" + (int)ch + ";");
}
}
return sb.toString();
}
// description and input are String variables containing values obtained from a database
// description = "description" and input = "2 items available"
public static void display(String description, String input) throws ValidationException {
ValidateOutput vo = new ValidateOutput();
vo.validate(description, input);
// Pass to another system or display to the user
}
}
|
...