...
Code Block | ||
---|---|---|
| ||
@RequestMapping("/getnotifications.htm") public ModelAndView getNotifications( HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView(); try { UserInfo userDetails = getUserInfo(); List<Map<String,Object>> list = new ArrayList<Map<String, Object>>(); List<Notification> notificationList = NotificationService.getNotificationsForUserId(userDetails.getPersonId()); 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; } |
...
Code Block | ||
---|---|---|
| ||
public class ValidateOutput {
// Allows only alphanumeric characters and spaces
private static final Pattern pattern = Pattern.compile("^[a-zA-Z0-9\\s]{0,20}$");
// Validates and encodes the input field based on a whitelist
public 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 nonvalid 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 nonvalid data
private 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();
}
}
// ...
@RequestMapping("/getnotifications.htm")
public ModelAndView getNotifications(HttpServletRequest request, HttpServletResponse response) {
ValidateOutput vo = new ValidateOutput();
ModelAndView mv = new ModelAndView();
try {
UserInfo userDetails = getUserInfo();
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
List<Notification> notificationList =
NotificationService.getNotificationsForUserId(userDetails.getPersonId());
for (Notification notification: notificationList) {
Map<String,Object> map = new HashMap<String,Object>();
map.put("id", vo.validate("id" ,notification.getId()));
map.put("message", vo.validate("message", notification.getMessage()));
list.add(map);
}
mv.addObject("Notifications",list);
}
catch(Throwable t){
// Log to file and handle
}
return mv;
}
|
Output encoding and escaping is mandatory when accepting dangerous characters such as double quotes and angle braces. Even when input is white-listed whitelisted to disallow such characters, output escaping is recommended because it provides a second level of defense. Note that the exact escape sequence can vary depending on where the output is embedded. For example, untrusted output may occur in an HTML value attribute, CSS, URL, or script; output encoding routine will be different in each case. It is also impossible to securely use untrusted data in some contexts. For example, untrusted output may occur in an HTML value attribute, CSS, URL or script and the output encoding routine will differ in each case. Consult the OWASP XSS (Cross Site Scripting) Prevention Cheat Sheet for more information on preventing XSS attacks.
...
The Apache GERONIMO-1474 vulnerability, reported in January 2006, allowed attackers to submit URLs containing JavaScript. The Web-Access-Log viewer failed to sanitize the data it forwarded to the administrator console, thereby enabling a classic XSS attack.
Bibliography
[OWASP 2011] | Cross-site Scripting (XSS) | ||
[OWASP 2014 2008] | How to Add Validation Logic to HttpServletRequest XSS (Cross Site Scripting) Prevention Cheat Sheet | [OWASP 2011] | Cross-site Scripting (XSS) |
...